From 51399fd8f1df26790c29e35e98f026627c2582fd Mon Sep 17 00:00:00 2001 From: tischsoic Date: Sat, 28 Mar 2026 11:37:38 +0100 Subject: [PATCH 01/30] IBX-11507-use-ds-radio-button: include DS base styles in admin UI --- src/bundle/Resources/encore/ibexa.css.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bundle/Resources/encore/ibexa.css.config.js b/src/bundle/Resources/encore/ibexa.css.config.js index 62dfba962e..283f45eb1f 100644 --- a/src/bundle/Resources/encore/ibexa.css.config.js +++ b/src/bundle/Resources/encore/ibexa.css.config.js @@ -5,6 +5,7 @@ module.exports = (Encore) => { path.resolve(__dirname, '../public/scss/ibexa-bootstrap.scss'), path.resolve(__dirname, '../public/scss/ibexa.scss'), path.resolve(__dirname, '../public/scss/ui/ibexa-modules.scss'), + path.resolve('./vendor/ibexa/admin-ui-assets/src/bundle/Resources/public/vendors/ids-assets/dist/css/styles.css'), path.resolve('./vendor/ibexa/admin-ui-assets/src/bundle/Resources/public/vendors/flatpickr/dist/flatpickr.min.css'), path.resolve( './vendor/ibexa/admin-ui-assets/src/bundle/Resources/public/vendors/flatpickr/dist/plugins/confirmDate/confirmDate.css', From 7892aa3264fdf516ab238c9b08ef78bbd17028bb Mon Sep 17 00:00:00 2001 From: tischsoic Date: Tue, 5 May 2026 08:00:31 +0200 Subject: [PATCH 02/30] IBX-11413: add DS dropdown compatibility wrapper --- .../Resources/encore/ibexa.js.config.js | 4 + .../public/js/scripts/filters.action.btns.js | 10 +- .../js/scripts/sidebar/extra.actions.js | 2 +- .../admin/content/tab/content.html.twig | 4 +- .../admin/content_type/tab/view.html.twig | 4 +- .../component/dropdown/dropdown_ds.html.twig | 201 ++++++++++++++++++ .../dropdown/dropdown_ds_multi.html.twig | 27 +++ .../dropdown/dropdown_ds_single.html.twig | 17 ++ .../ui/form_fields/dropdown_widget.html.twig | 2 +- 9 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig create mode 100644 src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig create mode 100644 src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig diff --git a/src/bundle/Resources/encore/ibexa.js.config.js b/src/bundle/Resources/encore/ibexa.js.config.js index 30b8296fd9..b12c548364 100644 --- a/src/bundle/Resources/encore/ibexa.js.config.js +++ b/src/bundle/Resources/encore/ibexa.js.config.js @@ -7,6 +7,10 @@ const layout = [ path.resolve(__dirname, '../public/js/scripts/admin.format.date.js'), path.resolve(__dirname, '../public/js/scripts/core/draggable.js'), path.resolve(__dirname, '../public/js/scripts/core/dropdown.js'), + path.resolve( + __dirname, + '../../../../../design-system-twig/src/bundle/Resources/public/ts/init_components.ts', + ), path.resolve(__dirname, '../public/js/scripts/core/backdrop.js'), path.resolve(__dirname, '../public/js/scripts/core/custom.tooltip.js'), path.resolve(__dirname, '../public/js/scripts/core/base.chart.js'), diff --git a/src/bundle/Resources/public/js/scripts/filters.action.btns.js b/src/bundle/Resources/public/js/scripts/filters.action.btns.js index ea1569d8f3..c7f2566bc5 100644 --- a/src/bundle/Resources/public/js/scripts/filters.action.btns.js +++ b/src/bundle/Resources/public/js/scripts/filters.action.btns.js @@ -4,7 +4,7 @@ containers.forEach((container) => { const clearBtn = container.querySelector('.ibexa-adaptive-filters__clear-btn'); const applyBtn = container.querySelector('.ibexa-adaptive-filters__submit-btn'); - const dropdownNodes = [...container.querySelectorAll('.ibexa-dropdown')]; + const dropdownNodes = [...container.querySelectorAll('.ibexa-dropdown, .ids-dropdown')]; const textInputNodes = [...container.querySelectorAll('.ibexa-input--text')]; const dateInputNodes = [...container.querySelectorAll('.ibexa-input--date')]; const originalValuesMap = new Map(); @@ -40,8 +40,8 @@ return ( textInputNodes.every((textInputNode) => textInputNode.disabled || textInputNode.value === '') && dropdownNodes.every((dropdownNode) => { - const isDisabled = dropdownNode.classList.contains('ibexa-dropdown--disabled'); - const selectNode = dropdownNode.querySelector('.ibexa-input--select'); + const isDisabled = dropdownNode.classList.contains('ibexa-dropdown--disabled') || dropdownNode.classList.contains('ids-dropdown--disabled'); + const selectNode = dropdownNode.querySelector('.ibexa-input--select, .ids-dropdown__source select'); const dropdown = dropdownNode.ibexaInstance; return isDisabled || (dropdown.canSelectOnlyOne ? selectNode.selectedIndex === 0 : selectNode.selectedIndex === -1); @@ -78,7 +78,7 @@ } }); dropdownNodes.forEach((dropdownNode) => { - const isDisabled = dropdownNode.classList.contains('ibexa-dropdown--disabled'); + const isDisabled = dropdownNode.classList.contains('ibexa-dropdown--disabled') || dropdownNode.classList.contains('ids-dropdown--disabled'); if (!isDisabled) { const dropdown = dropdownNode.ibexaInstance; @@ -135,7 +135,7 @@ } dropdownNodes.forEach((dropdownNode) => { - const select = dropdownNode.querySelector('.ibexa-input--select'); + const select = dropdownNode.querySelector('.ibexa-input--select, .ids-dropdown__source select'); select.addEventListener('change', handleInputChange, false); }); diff --git a/src/bundle/Resources/public/js/scripts/sidebar/extra.actions.js b/src/bundle/Resources/public/js/scripts/sidebar/extra.actions.js index e531ccf33c..ded5d4d6c3 100644 --- a/src/bundle/Resources/public/js/scripts/sidebar/extra.actions.js +++ b/src/bundle/Resources/public/js/scripts/sidebar/extra.actions.js @@ -36,7 +36,7 @@ import { getInstance } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scri node.checked = value; } else if (node.tagName === 'SELECT') { - const dropdownContainer = node.closest('.ibexa-dropdown'); + const dropdownContainer = node.closest('.ibexa-dropdown, .ids-dropdown'); if (dropdownContainer) { const dropdownInstance = getInstance(dropdownContainer); diff --git a/src/bundle/Resources/views/themes/admin/content/tab/content.html.twig b/src/bundle/Resources/views/themes/admin/content/tab/content.html.twig index 9686cd352f..4dcbf9ff5c 100644 --- a/src/bundle/Resources/views/themes/admin/content/tab/content.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/tab/content.html.twig @@ -36,12 +36,12 @@ {% endset %} - {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with { + {% include '@ibexadesign/ui/component/dropdown/dropdown_ds.html.twig' with { source: source, choices: choices, value: value, is_small: true, - } %} + } only %} {% endif %} {% endblock %} diff --git a/src/bundle/Resources/views/themes/admin/content_type/tab/view.html.twig b/src/bundle/Resources/views/themes/admin/content_type/tab/view.html.twig index 8e44d00a31..63d6b7e373 100644 --- a/src/bundle/Resources/views/themes/admin/content_type/tab/view.html.twig +++ b/src/bundle/Resources/views/themes/admin/content_type/tab/view.html.twig @@ -79,12 +79,12 @@ {% endset %} - {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with { + {% include '@ibexadesign/ui/component/dropdown/dropdown_ds.html.twig' with { source: source, choices: choices, value: value, is_small: true, - } %} + } only %} {% endif %} {% endset %} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig new file mode 100644 index 0000000000..44a9e9fb92 --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -0,0 +1,201 @@ +{% set preferred_choices = preferred_choices|default([]) %} +{% set translation_domain = translation_domain|default(false) %} +{% set value = value is defined ? value : null %} +{% set multiple = multiple|default(false) %} +{% set custom_init = custom_init|default(false) %} +{% set is_disabled = is_disabled|default(false) or attr.readonly|default(false) %} +{% set max_visible_items = 5 %} +{% set item_template_props = { + id: '{{ id }}', + label: '{{ label }}', +} %} +{% set preferred_choices_flat = preferred_choices + | map(choice => choice.choices is defined ? choice.choices : [choice]) + | reduce((carry, choices) => carry|merge(choices), []) +%} +{% set choices_flat = choices + | map(choice => choice.choices is defined ? choice.choices : [choice]) + | reduce((carry, choices) => carry|merge(choices), []) +%} + +{% set normalized_preferred_choices = preferred_choices + | map(choice => choice.choices is defined + ? choice.choices|map(child => { + value: child.value ~ '', + label: '[' + ~ (translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain)) + ~ ']: ' + ~ (translation_domain is same as(false) ? child.label : child.label|trans({}, translation_domain)), + }) + : [{ + value: choice.value ~ '', + label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), + }] + ) + | reduce((carry, choices) => carry|merge(choices), []) +%} +{% set normalized_choices = choices + | map(choice => choice.choices is defined + ? choice.choices|map(child => { + value: child.value ~ '', + label: '[' + ~ (translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain)) + ~ ']: ' + ~ (translation_domain is same as(false) ? child.label : child.label|trans({}, translation_domain)), + }) + : [{ + value: choice.value ~ '', + label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), + }] + ) + | reduce((carry, choices) => carry|merge(choices), []) +%} +{% set normalized_choices_data = normalized_preferred_choices + | merge(normalized_choices) + | reduce((carry, choice) => choice.value in carry.values + ? carry + : { + items: carry.items|merge([choice]), + values: carry.values|merge([choice.value]), + }, { + items: [], + values: [], + }) +%} +{% set normalized_items = normalized_choices_data.items %} +{% set has_icons = item_icon is defined + or preferred_choices_flat|filter(choice => choice.icon is defined)|length > 0 + or choices_flat|filter(choice => choice.icon is defined)|length > 0 +%} +{% set placeholder = placeholder is defined and placeholder is not none + ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) + : null +%} +{% set normalized_ds_items = normalized_items|map(choice => { + id: choice.value, + label: choice.label, +}) %} +{% set ds_items = not multiple and placeholder is not same as(null) + ? [{ id: '', label: placeholder }]|merge(normalized_ds_items) + : normalized_ds_items +%} +{% set ds_value = multiple + ? (value is iterable ? value|map(item => item ~ '') : []) + : (value is not null ? value ~ '' : '') +%} +{% set has_selected_item_template_path = selected_item_template_path is defined and selected_item_template_path is not null %} +{% set has_list_item_template_path = list_item_template_path is defined and list_item_template_path is not null %} +{% set has_selected_item_label = selected_item_label is defined and selected_item_label is not empty %} +{% set has_items_class = items_class is defined and items_class is not empty %} +{% set has_items_list_header = items_list_header is defined and items_list_header is not empty %} +{% set has_min_search_items = min_search_items is defined and min_search_items is not null %} +{% set has_min_select_all_toggler_items = min_select_all_toggler_items is defined and min_select_all_toggler_items is not null %} +{% set has_min_item_width = min_item_width is defined and min_item_width is not null %} +{% set selected_items = multiple ? ds_items|filter(item => item.id in ds_value) : [] %} +{% set selected_item = not multiple + ? (ds_items|filter(item => item.id == ds_value)|first) + : null +%} +{% set default_selected_item = not multiple and (placeholder is not defined or placeholder is same as(null)) + ? ds_items|first + : null +%} +{% set effective_selected_item = selected_item ?: default_selected_item %} +{% set selected_label = effective_selected_item.label|default('') %} +{% set is_empty = multiple ? ds_value is empty : effective_selected_item is null %} +{% set can_use_ds = not ( + custom_init + or has_selected_item_template_path + or has_list_item_template_path + or has_selected_item_label + or is_dynamic|default(false) + or is_selector|default(false) + or has_items_class + or has_items_list_header + or is_small|default(false) + or is_ghost|default(false) + or has_min_search_items + or has_min_item_width +) %} + +{% if can_use_ds %} + {% include multiple + ? '@ibexadesign/ui/component/dropdown/dropdown_ds_multi.html.twig' + : '@ibexadesign/ui/component/dropdown/dropdown_ds_single.html.twig' + with { + source: source|default(''), + items: ds_items, + value: ds_value, + selected_items: selected_items, + selected_label: selected_label, + is_empty: is_empty, + is_search_visible: ds_items|length >= max_visible_items, + max_visible_items: max_visible_items, + item_template_props: item_template_props, + disabled: is_disabled, + error: false, + class: class|default(''), + name: name|default('dropdown'), + placeholder: placeholder, + } only %} +{% else %} + {% set legacy_context = { + source: source|default(null), + choices: choices, + preferred_choices: preferred_choices, + value: value, + multiple: multiple, + custom_init: custom_init, + class: class|default(''), + translation_domain: translation_domain, + custom_form: custom_form is defined ? custom_form : true, + is_disabled: is_disabled, + is_hidden: is_hidden|default(false), + is_small: is_small|default(false), + is_ghost: is_ghost|default(false), + is_selector: is_selector|default(false), + is_dynamic: is_dynamic|default(false), + has_select_all_toggler: has_select_all_toggler|default(false), + placeholder: placeholder, + item_icon_class: item_icon_class|default(''), + attr: attr|default({}), + } %} + {% set legacy_context = has_selected_item_template_path + ? legacy_context|merge({ selected_item_template_path: selected_item_template_path }) + : legacy_context + %} + {% set legacy_context = has_list_item_template_path + ? legacy_context|merge({ list_item_template_path: list_item_template_path }) + : legacy_context + %} + {% set legacy_context = has_items_class + ? legacy_context|merge({ items_class: items_class }) + : legacy_context + %} + {% set legacy_context = has_items_list_header + ? legacy_context|merge({ items_list_header: items_list_header }) + : legacy_context + %} + {% set legacy_context = item_icon is defined and item_icon is not null + ? legacy_context|merge({ item_icon: item_icon }) + : legacy_context + %} + {% set legacy_context = has_min_search_items + ? legacy_context|merge({ min_search_items: min_search_items }) + : legacy_context + %} + {% set legacy_context = has_min_select_all_toggler_items + ? legacy_context|merge({ min_select_all_toggler_items: min_select_all_toggler_items }) + : legacy_context + %} + {% set legacy_context = has_min_item_width + ? legacy_context|merge({ min_item_width: min_item_width }) + : legacy_context + %} + {% set legacy_context = has_selected_item_label + ? legacy_context|merge({ selected_item_label: selected_item_label }) + : legacy_context + %} + + {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with legacy_context only %} +{% endif %} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig new file mode 100644 index 0000000000..7d36ccb313 --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig @@ -0,0 +1,27 @@ +{% extends '@IbexaDesignSystemTwig/themes/standard/design_system/partials/base_dropdown.html.twig' %} + +{% set class = html_classes('ids-dropdown--multi', class|default('')) %} + +{% block source %} + {{ source|raw }} +{% endblock source %} + +{% block placeholder %} +
+ {{ placeholder|default('ibexa.dropdown.placeholder'|trans({}, 'ibexa_design_system_twig')) }} +
+{% endblock placeholder %} + +{% block item_content %} + + {{ item.label }} +{% endblock item_content %} + +{% block selected_items %} + {{ selected_items|map(item => item.label)|join(', ') }} +{% endblock selected_items %} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig new file mode 100644 index 0000000000..5d5d6dedac --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig @@ -0,0 +1,17 @@ +{% extends '@IbexaDesignSystemTwig/themes/standard/design_system/partials/base_dropdown.html.twig' %} + +{% set class = html_classes('ids-dropdown--single', class|default('')) %} + +{% block source %} + {{ source|raw }} +{% endblock source %} + +{% block placeholder %} +
+ {{ placeholder|default('ibexa.dropdown.placeholder'|trans({}, 'ibexa_design_system_twig')) }} +
+{% endblock placeholder %} + +{% block selected_items %} + {{ selected_label }} +{% endblock selected_items %} diff --git a/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig b/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig index 70dc38cf11..d4e35a50de 100644 --- a/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig @@ -9,7 +9,7 @@ {{- block('choice_widget_collapsed') -}} {% endset %} - {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with { + {% include '@ibexadesign/ui/component/dropdown/dropdown_ds.html.twig' with { source: source, choices: choices, preferred_choices: preferred_choices, From 721f6f8e04cb0f51ecd0bfd228a35fe998b7f238 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Tue, 5 May 2026 08:45:39 +0200 Subject: [PATCH 03/30] fix: support DS dropdowns in admin UI dynamic flows --- .../js/scripts/admin.contenttype.edit.js | 45 ++++++++++++++----- .../scripts/admin.location.add.custom_url.js | 12 ++++- .../js/scripts/admin.notifications.filters.js | 7 +-- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.contenttype.edit.js b/src/bundle/Resources/public/js/scripts/admin.contenttype.edit.js index eb8935244d..4c9c04a2ef 100644 --- a/src/bundle/Resources/public/js/scripts/admin.contenttype.edit.js +++ b/src/bundle/Resources/public/js/scripts/admin.contenttype.edit.js @@ -1,3 +1,5 @@ +import { DropdownMultiInput, DropdownSingleInput } from '../../../../../../../design-system-twig/src/bundle/Resources/public/ts/components/dropdown'; + (function (global, doc, ibexa, Routing, Translator, bootstrap) { const SELECTOR_INPUTS_TO_VALIDATE = '.ibexa-input[required]:not([disabled]):not([hidden])'; const SELETOR_FIELD_INPUTS = @@ -102,6 +104,35 @@ return fieldNode; }; const attachFieldDefinitionNodeEvents = (fieldNode, { targetContainer }) => { + const initDropdown = (dropdownContainer) => { + const dropdownAlreadyInitialized = !!ibexa.helpers.objectInstances.getInstance(dropdownContainer); + + if (dropdownAlreadyInitialized) { + return; + } + + if (dropdownContainer.classList.contains('ids-dropdown--multi')) { + const dropdown = new DropdownMultiInput(dropdownContainer); + + dropdown.init(); + + return; + } + + if (dropdownContainer.classList.contains('ids-dropdown--single')) { + const dropdown = new DropdownSingleInput(dropdownContainer); + + dropdown.init(); + + return; + } + + const dropdown = new ibexa.core.Dropdown({ + container: dropdownContainer, + }); + + dropdown.init(); + }; const fieldGroupInput = fieldNode.querySelector('.ibexa-input--field-group'); const fieldDefinitionsInputs = fieldNode.querySelectorAll(SELETOR_FIELD_INPUTS); const removeFieldBtns = fieldNode.querySelectorAll('.ibexa-collapse__extra-action-button--remove-field-definitions'); @@ -122,20 +153,10 @@ }); } - const dropdowns = fieldNode.querySelectorAll('.ibexa-dropdown'); + const dropdowns = fieldNode.querySelectorAll('.ibexa-dropdown, .ids-dropdown'); dropdowns.forEach((dropdownContainer) => { - const dropdownAlreadyInitialized = !!ibexa.helpers.objectInstances.getInstance(dropdownContainer); - - if (dropdownAlreadyInitialized) { - return; - } - - const dropdown = new ibexa.core.Dropdown({ - container: dropdownContainer, - }); - - dropdown.init(); + initDropdown(dropdownContainer); }); draggableGroups.forEach((group) => { diff --git a/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js b/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js index 8668cff04f..3766be2f01 100644 --- a/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js +++ b/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js @@ -18,11 +18,19 @@ }; const toggleSiteAccessSelect = (event) => { const isChecked = event.target.checked; - const siteAccessSelect = modal.querySelector('.ibexa-custom-url-from__item--siteacces .ibexa-dropdown'); + const siteAccessSelect = modal.querySelector('.ibexa-custom-url-from__item--siteacces .ibexa-dropdown, .ibexa-custom-url-from__item--siteacces .ids-dropdown'); + const sourceSelect = siteAccessSelect?.querySelector('.ibexa-input--select, .ids-dropdown__source select'); - siteAccessSelect.classList.toggle('ibexa-dropdown--is-disabled', isChecked); + siteAccessSelect?.classList.toggle('ibexa-dropdown--is-disabled', isChecked); + siteAccessSelect?.classList.toggle('ibexa-dropdown--disabled', isChecked); + siteAccessSelect?.classList.toggle('ids-dropdown--disabled', isChecked); + + if (sourceSelect) { + sourceSelect.disabled = isChecked; + } }; + toggleSiteAccessSelect({ target: siteRootCheckbox }); input.addEventListener('input', toggleButtonState, false); siteRootCheckbox.addEventListener('change', toggleSiteAccessSelect, false); discardBtns.forEach((btn) => btn.addEventListener('click', clearValues, false)); diff --git a/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js b/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js index 33fb21d9d9..594de83356 100644 --- a/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js +++ b/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js @@ -1,4 +1,5 @@ (function (global, doc) { + const SELECTOR_DROPDOWN_SOURCE_SELECT = '.ibexa-dropdown__source .ibexa-input--select, .ids-dropdown__source select'; const searchForm = doc.querySelector('.ibexa-list-search-form'); const filtersContainerNode = doc.querySelector('.ibexa-list-filters'); const applyFiltersBtn = filtersContainerNode.querySelector('.ibexa-btn--apply'); @@ -12,7 +13,7 @@ return; } - const sourceSelect = filterNode.querySelector('.ibexa-list-filters__item-content .ibexa-dropdown__source .ibexa-input--select'); + const sourceSelect = filterNode.querySelector(`.ibexa-list-filters__item-content ${SELECTOR_DROPDOWN_SOURCE_SELECT}`); const checkboxes = filterNode.querySelectorAll( '.ibexa-list-filters__item-content .ibexa-input--checkbox:not([name="dropdown-checkbox"])', ); @@ -57,7 +58,7 @@ return; } - const sourceSelect = filterNode.querySelector('.ibexa-list-filters__item-content .ibexa-dropdown__source .ibexa-input--select'); + const sourceSelect = filterNode.querySelector(`.ibexa-list-filters__item-content ${SELECTOR_DROPDOWN_SOURCE_SELECT}`); sourceSelect?.addEventListener('change', filterChange, false); }; @@ -79,7 +80,7 @@ return; } - const select = filterNode.querySelector('.ibexa-dropdown__source .ibexa-input--select'); + const select = filterNode.querySelector(SELECTOR_DROPDOWN_SOURCE_SELECT); const checkedCheckboxes = filterNode.querySelectorAll('.ibexa-input--checkbox:checked'); if (isNodeDatePicker(filterNode)) { From 51c949e9816cf6fe151a2ad364f10c952a878fe3 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Wed, 6 May 2026 09:04:19 +0200 Subject: [PATCH 04/30] fix: pass hidden state to DS dropdown wrapper --- .../themes/admin/ui/component/dropdown/dropdown_ds.html.twig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 44a9e9fb92..be2d5e37e5 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -119,6 +119,7 @@ ) %} {% if can_use_ds %} + {# {{ dump() }} #} {% include multiple ? '@ibexadesign/ui/component/dropdown/dropdown_ds_multi.html.twig' : '@ibexadesign/ui/component/dropdown/dropdown_ds_single.html.twig' @@ -135,6 +136,9 @@ disabled: is_disabled, error: false, class: class|default(''), + attributes: { + hidden: is_hidden|default(false), + }, name: name|default('dropdown'), placeholder: placeholder, } only %} From 2644efb8ccea1d97c92852bf3d23d4e63f94f164 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Wed, 6 May 2026 13:32:06 +0200 Subject: [PATCH 05/30] fix: keep DS dropdown placeholder behavior consistent --- .../component/dropdown/dropdown_ds.html.twig | 18 +++++++++++------- .../dropdown/dropdown_ds_multi.html.twig | 6 ------ .../dropdown/dropdown_ds_single.html.twig | 6 ------ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index be2d5e37e5..975f9dd708 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -67,16 +67,21 @@ or preferred_choices_flat|filter(choice => choice.icon is defined)|length > 0 or choices_flat|filter(choice => choice.icon is defined)|length > 0 %} -{% set placeholder = placeholder is defined and placeholder is not none +{% set translated_placeholder = placeholder is defined and placeholder is not none ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) : null %} +{% set empty_placeholder_fallback = 'ibexa.dropdown.placeholder.all'|trans({}, 'ibexa_design_system_twig')|desc('All') %} +{% set empty_placeholder_label = translated_placeholder is not same as(null) + ? translated_placeholder|trim|default(empty_placeholder_fallback) + : null +%} {% set normalized_ds_items = normalized_items|map(choice => { id: choice.value, label: choice.label, }) %} -{% set ds_items = not multiple and placeholder is not same as(null) - ? [{ id: '', label: placeholder }]|merge(normalized_ds_items) +{% set ds_items = not multiple and translated_placeholder is not same as(null) + ? [{ id: '', label: empty_placeholder_label }]|merge(normalized_ds_items) : normalized_ds_items %} {% set ds_value = multiple @@ -96,7 +101,7 @@ ? (ds_items|filter(item => item.id == ds_value)|first) : null %} -{% set default_selected_item = not multiple and (placeholder is not defined or placeholder is same as(null)) +{% set default_selected_item = not multiple and translated_placeholder is same as(null) ? ds_items|first : null %} @@ -119,7 +124,6 @@ ) %} {% if can_use_ds %} - {# {{ dump() }} #} {% include multiple ? '@ibexadesign/ui/component/dropdown/dropdown_ds_multi.html.twig' : '@ibexadesign/ui/component/dropdown/dropdown_ds_single.html.twig' @@ -140,7 +144,7 @@ hidden: is_hidden|default(false), }, name: name|default('dropdown'), - placeholder: placeholder, + placeholder: translated_placeholder, } only %} {% else %} {% set legacy_context = { @@ -160,7 +164,7 @@ is_selector: is_selector|default(false), is_dynamic: is_dynamic|default(false), has_select_all_toggler: has_select_all_toggler|default(false), - placeholder: placeholder, + placeholder: translated_placeholder, item_icon_class: item_icon_class|default(''), attr: attr|default({}), } %} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig index 7d36ccb313..210653b8fc 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig @@ -6,12 +6,6 @@ {{ source|raw }} {% endblock source %} -{% block placeholder %} -
- {{ placeholder|default('ibexa.dropdown.placeholder'|trans({}, 'ibexa_design_system_twig')) }} -
-{% endblock placeholder %} - {% block item_content %} - {{ placeholder|default('ibexa.dropdown.placeholder'|trans({}, 'ibexa_design_system_twig')) }} - -{% endblock placeholder %} - {% block selected_items %} {{ selected_label }} {% endblock selected_items %} From 9da020ab775f7ce533c2dd41d28b1d80558a595a Mon Sep 17 00:00:00 2001 From: tischsoic Date: Thu, 7 May 2026 09:29:29 +0200 Subject: [PATCH 06/30] fix: render multi dropdown selections as chips --- .../Resources/public/scss/_dropdown.scss | 8 ++++ .../dropdown/dropdown_ds_multi.html.twig | 37 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/bundle/Resources/public/scss/_dropdown.scss b/src/bundle/Resources/public/scss/_dropdown.scss index 319de4f673..e407e47d31 100644 --- a/src/bundle/Resources/public/scss/_dropdown.scss +++ b/src/bundle/Resources/public/scss/_dropdown.scss @@ -561,6 +561,14 @@ } } +.ids-dropdown { + &__selection-info, + &__selection-info-items, + .ids-overflow-list { + min-width: 0; + } +} + .form-inline { .ibexa-dropdown { margin: calculateRem(5px) calculateRem(8px); diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig index 210653b8fc..fa218edc42 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig @@ -1,6 +1,13 @@ {% extends '@IbexaDesignSystemTwig/themes/standard/design_system/partials/base_dropdown.html.twig' %} +{% trans_default_domain 'ibexa_design_system_twig' %} + {% set class = html_classes('ids-dropdown--multi', class|default('')) %} +{% set selected_item_template_props = { + id: '{{ id }}', + label: '{{ label }}', +} %} +{% set hidden_count_template = '{{ hidden_count }}' %} {% block source %} {{ source|raw }} @@ -17,5 +24,33 @@ {% endblock item_content %} {% block selected_items %} - {{ selected_items|map(item => item.label)|join(', ') }} +
+
+ {% for item in selected_items %} + + {{ item.label }} + + {% endfor %} + + +
+ + +
{% endblock selected_items %} From 6be910949d8eb8272333432bc9f754d604996213 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Thu, 7 May 2026 12:30:12 +0200 Subject: [PATCH 07/30] refactor: reuse shared overflow list markup --- .../dropdown/dropdown_ds_multi.html.twig | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig index fa218edc42..884de4a1c2 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig @@ -24,14 +24,18 @@ {% endblock item_content %} {% block selected_items %} -
-
- {% for item in selected_items %} - - {{ item.label }} - - {% endfor %} + {% embed '@IbexaDesignSystemTwig/themes/standard/design_system/components/overflow_list.html.twig' with { + items: selected_items, + item_template_props: selected_item_template_props, + hidden_count_template: hidden_count_template, + } only %} + {% block item %} + + {{ item.label }} + + {% endblock item %} + {% block more_item_current %} +0 -
- - -
+ {% endblock more_item_template %} + {% endembed %} {% endblock selected_items %} From 7e98f297eebf167ab67dd123274042837fff5944 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Thu, 7 May 2026 14:28:59 +0200 Subject: [PATCH 08/30] refactor: render flat dropdowns with DS inputs directly --- .../public/js/scripts/admin.search.filters.js | 26 +++++--- .../component/dropdown/dropdown_ds.html.twig | 64 ++++++++----------- .../dropdown/dropdown_ds_multi.html.twig | 54 ---------------- .../dropdown/dropdown_ds_single.html.twig | 11 ---- 4 files changed, 43 insertions(+), 112 deletions(-) delete mode 100644 src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig delete mode 100644 src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig diff --git a/src/bundle/Resources/public/js/scripts/admin.search.filters.js b/src/bundle/Resources/public/js/scripts/admin.search.filters.js index 7f6b1dcc1c..71f405a3c2 100644 --- a/src/bundle/Resources/public/js/scripts/admin.search.filters.js +++ b/src/bundle/Resources/public/js/scripts/admin.search.filters.js @@ -2,17 +2,22 @@ const { escapeHTML, escapeHTMLAttribute } = ibexa.helpers.text; const { dangerouslySetInnerHTML } = ibexa.helpers.dom; const { getInstance } = ibexa.helpers.objectInstances; + const SELECTOR_DROPDOWN = '.ibexa-dropdown, .ids-dropdown'; + const SELECTOR_DROPDOWN_SOURCE_SELECT = '.ibexa-input--select, .ids-dropdown__source select'; let getUsersTimeout; const SELECTOR_TAG = '.ibexa-tag'; const token = doc.querySelector('meta[name="CSRF-Token"]').content; const siteaccess = doc.querySelector('meta[name="SiteAccess"]').content; const filters = doc.querySelector('.ibexa-filters'); + const getDropdownContainer = (selector) => filters.querySelector(`${selector} ${SELECTOR_DROPDOWN}`); + const getDropdownSourceSelect = (selector) => filters.querySelector(`${selector} ${SELECTOR_DROPDOWN_SOURCE_SELECT}`); const clearBtn = filters.querySelector('.ibexa-btn--clear'); const applyBtn = filters.querySelector('.ibexa-btn--apply'); const contentTypeSelect = doc.querySelector('.ibexa-filters__item--content-type .ibexa-filters__select'); - const sectionSelect = doc.querySelector('.ibexa-filters__item--section .ibexa-filters__select'); - const lastModifiedSelectNode = doc.querySelector('.ibexa-filters__item--modified .ibexa-filters__select'); - const lastModifiedSelect = getInstance(lastModifiedSelectNode); + const sectionSelect = getDropdownSourceSelect('.ibexa-filters__item--section'); + const lastModifiedDropdownNode = getDropdownContainer('.ibexa-filters__item--modified'); + const lastModifiedSelectNode = getDropdownSourceSelect('.ibexa-filters__item--modified'); + const lastModifiedSelect = getInstance(lastModifiedDropdownNode); const lastModifiedDateRangeNode = doc.querySelector('.ibexa-filters__item--modified .ibexa-date-time-range-single'); const lastModifiedDateRange = getInstance(lastModifiedDateRangeNode); const { @@ -23,8 +28,9 @@ const lastModifiedPeriod = doc.querySelector(lastModifiedPeriodSelector); const lastModifiedStartDate = doc.querySelector(lastModifiedStartSelector); const lastModifiedEndDate = doc.querySelector(lastModifiedEndSelector); - const lastCreatedSelectNode = doc.querySelector('.ibexa-filters__item--created .ibexa-filters__select'); - const lastCreatedSelect = getInstance(lastCreatedSelectNode); + const lastCreatedDropdownNode = getDropdownContainer('.ibexa-filters__item--created'); + const lastCreatedSelectNode = getDropdownSourceSelect('.ibexa-filters__item--created'); + const lastCreatedSelect = getInstance(lastCreatedDropdownNode); const lastCreatedDateRangeNode = doc.querySelector('.ibexa-filters__item--created .ibexa-date-time-range-single'); const lastCreatedDateRange = getInstance(lastCreatedDateRangeNode); const { @@ -63,9 +69,8 @@ sectionSelect[0].selected = true; } - lastModifiedSelectNode[0].selected = true; - lastCreatedSelectNode[0].selected = true; - lastModifiedSelectNode.querySelector('option').selected = true; + lastModifiedSelect.selectFirstOption(); + lastCreatedSelect.selectFirstOption(); lastModifiedPeriod.value = ''; lastModifiedEnd.value = ''; lastCreatedPeriod.value = ''; @@ -240,7 +245,10 @@ removeSearchTag(event); }; const clearSection = (event) => { - sectionSelect[0].selected = true; + if (sectionSelect) { + sectionSelect[0].selected = true; + } + removeSearchTag(event); }; const clearSubtree = (event) => { diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 975f9dd708..754c7c2538 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -5,10 +5,6 @@ {% set custom_init = custom_init|default(false) %} {% set is_disabled = is_disabled|default(false) or attr.readonly|default(false) %} {% set max_visible_items = 5 %} -{% set item_template_props = { - id: '{{ id }}', - label: '{{ label }}', -} %} {% set preferred_choices_flat = preferred_choices | map(choice => choice.choices is defined ? choice.choices : [choice]) | reduce((carry, choices) => carry|merge(choices), []) @@ -96,18 +92,8 @@ {% set has_min_search_items = min_search_items is defined and min_search_items is not null %} {% set has_min_select_all_toggler_items = min_select_all_toggler_items is defined and min_select_all_toggler_items is not null %} {% set has_min_item_width = min_item_width is defined and min_item_width is not null %} -{% set selected_items = multiple ? ds_items|filter(item => item.id in ds_value) : [] %} -{% set selected_item = not multiple - ? (ds_items|filter(item => item.id == ds_value)|first) - : null -%} -{% set default_selected_item = not multiple and translated_placeholder is same as(null) - ? ds_items|first - : null -%} -{% set effective_selected_item = selected_item ?: default_selected_item %} -{% set selected_label = effective_selected_item.label|default('') %} -{% set is_empty = multiple ? ds_value is empty : effective_selected_item is null %} +{% set has_grouped_preferred_choices = preferred_choices|filter(choice => choice.choices is defined)|length > 0 %} +{% set has_grouped_choices = choices|filter(choice => choice.choices is defined)|length > 0 %} {% set can_use_ds = not ( custom_init or has_selected_item_template_path @@ -121,31 +107,33 @@ or is_ghost|default(false) or has_min_search_items or has_min_item_width + or has_grouped_preferred_choices + or has_grouped_choices ) %} {% if can_use_ds %} - {% include multiple - ? '@ibexadesign/ui/component/dropdown/dropdown_ds_multi.html.twig' - : '@ibexadesign/ui/component/dropdown/dropdown_ds_single.html.twig' - with { - source: source|default(''), - items: ds_items, - value: ds_value, - selected_items: selected_items, - selected_label: selected_label, - is_empty: is_empty, - is_search_visible: ds_items|length >= max_visible_items, - max_visible_items: max_visible_items, - item_template_props: item_template_props, - disabled: is_disabled, - error: false, - class: class|default(''), - attributes: { - hidden: is_hidden|default(false), - }, - name: name|default('dropdown'), - placeholder: translated_placeholder, - } only %} + {% set ds_dropdown_props = { + name: name|default('dropdown'), + items: ds_items, + value: ds_value, + disabled: is_disabled, + maxVisibleItems: max_visible_items, + class: class|default(''), + } %} + {% set ds_dropdown_props = translated_placeholder is not same as(null) + ? ds_dropdown_props|merge({ placeholder: translated_placeholder }) + : ds_dropdown_props + %} + {% set ds_dropdown_props = is_hidden|default(false) + ? ds_dropdown_props|merge({ hidden: true }) + : ds_dropdown_props + %} + + {% if multiple %} + + {% else %} + + {% endif %} {% else %} {% set legacy_context = { source: source|default(null), diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig deleted file mode 100644 index 884de4a1c2..0000000000 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_multi.html.twig +++ /dev/null @@ -1,54 +0,0 @@ -{% extends '@IbexaDesignSystemTwig/themes/standard/design_system/partials/base_dropdown.html.twig' %} - -{% trans_default_domain 'ibexa_design_system_twig' %} - -{% set class = html_classes('ids-dropdown--multi', class|default('')) %} -{% set selected_item_template_props = { - id: '{{ id }}', - label: '{{ label }}', -} %} -{% set hidden_count_template = '{{ hidden_count }}' %} - -{% block source %} - {{ source|raw }} -{% endblock source %} - -{% block item_content %} - - {{ item.label }} -{% endblock item_content %} - -{% block selected_items %} - {% embed '@IbexaDesignSystemTwig/themes/standard/design_system/components/overflow_list.html.twig' with { - items: selected_items, - item_template_props: selected_item_template_props, - hidden_count_template: hidden_count_template, - } only %} - {% block item %} - - {{ item.label }} - - {% endblock item %} - - {% block more_item_current %} - - {% endblock more_item_current %} - - {% block more_item_template %} - - +{{ hidden_count_template }} - - {% endblock more_item_template %} - {% endembed %} -{% endblock selected_items %} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig deleted file mode 100644 index 2d2c3598cf..0000000000 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds_single.html.twig +++ /dev/null @@ -1,11 +0,0 @@ -{% extends '@IbexaDesignSystemTwig/themes/standard/design_system/partials/base_dropdown.html.twig' %} - -{% set class = html_classes('ids-dropdown--single', class|default('')) %} - -{% block source %} - {{ source|raw }} -{% endblock source %} - -{% block selected_items %} - {{ selected_label }} -{% endblock selected_items %} From f4b66e66f90f52d4798249fe73158ae187e0e185 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Fri, 8 May 2026 22:51:10 +0200 Subject: [PATCH 09/30] fix: wire DS dropdown context in UDW --- .../public/js/scripts/helpers/icon.helper.js | 4 +- .../design-system/design.system.provider.js | 30 ++ .../content.create.widget.js | 14 +- .../components/filters/filters.js | 25 +- .../universal.discovery.module.js | 261 +++++++++--------- 5 files changed, 182 insertions(+), 152 deletions(-) create mode 100644 src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js diff --git a/src/bundle/Resources/public/js/scripts/helpers/icon.helper.js b/src/bundle/Resources/public/js/scripts/helpers/icon.helper.js index f9d9193c28..a8b1d27fec 100644 --- a/src/bundle/Resources/public/js/scripts/helpers/icon.helper.js +++ b/src/bundle/Resources/public/js/scripts/helpers/icon.helper.js @@ -1,9 +1,9 @@ import { getAdminUiConfig } from './context.helper'; -const getIconPath = (aliasPath, iconSet) => { +const getIconPath = (iconName, iconSet, useLegacyNames = true) => { const adminUiConfig = getAdminUiConfig(); const { defaultIconSet, iconSets, iconAliases } = adminUiConfig.iconPaths; - const path = iconAliases[aliasPath] || aliasPath; + const path = useLegacyNames ? iconAliases[iconName] || iconName : iconName; if (!iconSet) { iconSet = defaultIconSet; diff --git a/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js b/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js new file mode 100644 index 0000000000..ef38ea08fa --- /dev/null +++ b/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js @@ -0,0 +1,30 @@ +import React, { useMemo } from 'react'; + +import { AssetsProvider, TranslatorProvider } from '@ids-components/context'; + +import { getTranslator } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scripts/helpers/context.helper'; +import { getIconPath } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scripts/helpers/icon.helper'; + +const DesignSystemProvider = ({ children }) => { + const Translator = getTranslator(); + const assetsContextValue = useMemo( + () => ({ + getIconPath: (iconName, iconSet) => getIconPath(iconName, iconSet, false), + }), + [], + ); + const translatorContextValue = useMemo( + () => ({ + trans: (key, parameters = {}, domain) => Translator.trans(key, parameters, domain), + }), + [Translator], + ); + + return ( + + {children} + + ); +}; + +export default DesignSystemProvider; diff --git a/src/bundle/ui-dev/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js b/src/bundle/ui-dev/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js index 0d2615d30c..26d18540d4 100644 --- a/src/bundle/ui-dev/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js +++ b/src/bundle/ui-dev/src/modules/universal-discovery/components/content-create-widget/content.create.widget.js @@ -2,10 +2,9 @@ import React, { useContext, useState, useEffect, useRef, useMemo } from 'react'; import { createCssClassNames } from '../../../common/helpers/css.class.names'; import Icon from '../../../common/icon/icon'; -import Dropdown from '../../../common/dropdown/dropdown'; +import { DropdownSingleInput } from '@ids-components/components/Dropdown'; import { - DropdownPortalRefContext, CreateContentWidgetContext, ActiveTabContext, ContentOnTheFlyDataContext, @@ -29,7 +28,6 @@ const ContentCreateWidget = () => { const Translator = getTranslator(); const adminUiConfig = getAdminUiConfig(); const refContentTree = useRef(null); - const dropdownListRef = useContext(DropdownPortalRefContext); const [markedLocationId] = useContext(MarkedLocationIdContext); const [loadedLocationsMap] = useContext(LoadedLocationsMapContext); const { allowedLanguages, preselectedLanguage, preselectedContentType } = useContext(ContentOnTheFlyConfigContext); @@ -189,13 +187,13 @@ const ContentCreateWidget = () => {
- ({ id: value, label }))} + maxVisibleItems={5} + name="" onChange={updateSelectedLanguage} - single={true} value={selectedLanguage} - options={languageOptions} - extraClasses="c-udw-dropdown" />
diff --git a/src/bundle/ui-dev/src/modules/universal-discovery/components/filters/filters.js b/src/bundle/ui-dev/src/modules/universal-discovery/components/filters/filters.js index 7a9e2a8a1c..41c9d7abe7 100644 --- a/src/bundle/ui-dev/src/modules/universal-discovery/components/filters/filters.js +++ b/src/bundle/ui-dev/src/modules/universal-discovery/components/filters/filters.js @@ -13,9 +13,9 @@ import { SelectedSubtreeBreadcrumbsContext, } from '../search/search'; -import UniversalDiscoveryModule, { DropdownPortalRefContext } from '../../universal.discovery.module'; +import UniversalDiscoveryModule from '../../universal.discovery.module'; -import Dropdown from '../../../common/dropdown/dropdown'; +import { DropdownSingleInput } from '@ids-components/components/Dropdown'; import ContentTypeSelector from '../content-type-selector/content.type.selector'; import Icon from '../../../common/icon/icon'; @@ -35,7 +35,6 @@ const Filters = ({ search }) => { const [selectedLanguage, setSelectedLanguage] = useContext(SelectedLanguageContext); const [selectedSubtreeBreadcrumbs, setSelectedSubtreeBreadcrumbs] = useContext(SelectedSubtreeBreadcrumbsContext); const prevSelectedLanguage = useRef(selectedLanguage); - const dropdownListRef = useContext(DropdownPortalRefContext); const [filtersCleared, setFiltersCleared] = useState(false); const [isNestedUdwOpened, setIsNestedUdwOpened] = useState(false); const filterSubtreeUdwConfig = JSON.parse(window.document.querySelector('#react-udw').dataset.filterSubtreeUdwConfig); @@ -152,24 +151,24 @@ const Filters = ({ search }) => { {isNestedUdwOpened && ReactDOM.createPortal(, nestedUdwContainer.current)} - ({ id: value, label }))} + maxVisibleItems={5} + name="" onChange={updateSelectedLanguage} value={selectedLanguage} - options={languageOptions} - extraClasses="ibexa-dropdown--small c-udw-dropdown" /> - ({ id: value, label }))} + maxVisibleItems={5} + name="" onChange={updateSection} value={selectedSection} - options={sectionOptions} - extraClasses="ibexa-dropdown--small c-udw-dropdown" /> diff --git a/src/bundle/ui-dev/src/modules/universal-discovery/universal.discovery.module.js b/src/bundle/ui-dev/src/modules/universal-discovery/universal.discovery.module.js index 062d87b193..1b891bcd5c 100644 --- a/src/bundle/ui-dev/src/modules/universal-discovery/universal.discovery.module.js +++ b/src/bundle/ui-dev/src/modules/universal-discovery/universal.discovery.module.js @@ -2,6 +2,7 @@ import React, { useEffect, useCallback, useState, createContext, useRef, useMemo import PropTypes from 'prop-types'; import Icon from '../common/icon/icon'; +import DesignSystemProvider from '../common/design-system/design.system.provider'; import deepClone from '../common/helpers/deep.clone.helper'; import { createCssClassNames } from '../common/helpers/css.class.names'; import { useLoadedLocationsReducer } from './hooks/useLoadedLocationsReducer'; @@ -540,164 +541,166 @@ const UniversalDiscoveryModule = ({ }, [currentView]); return ( -
- - - - - - - - - - - - - - - - - - - - - +
+ + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); }; From 51febe6de4faf9f992636ffdf490864b685ab846 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Sun, 10 May 2026 10:48:18 +0200 Subject: [PATCH 10/30] fix: preserve source select attributes in DS dropdowns --- .../component/dropdown/dropdown_ds.html.twig | 33 ++++++++++++++++++- .../ui/form_fields/dropdown_widget.html.twig | 4 +++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 754c7c2538..ea6464ad66 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -4,7 +4,36 @@ {% set multiple = multiple|default(false) %} {% set custom_init = custom_init|default(false) %} {% set is_disabled = is_disabled|default(false) or attr.readonly|default(false) %} +{% set source = source|default(null) %} +{% set source_attr = source_attr|default({}) %} +{% set source_id = source_id|default(source_attr.id|default(null)) %} +{% set source_name = source_name|default(source_attr.name|default(name|default('dropdown'))) %} {% set max_visible_items = 5 %} +{% set excluded_source_attr_keys = [ + 'dropdown_hidden', + 'dropdown_class', + 'dropdown_custom_init', + 'is_small', + 'is_ghost', + 'is_selector', + 'is_dynamic', + 'has_select_all_toggler', +] %} +{% set normalized_source_attr = {} %} +{% for key, item in source_attr %} + {% if key not in excluded_source_attr_keys %} + {% set normalized_source_attr = normalized_source_attr|merge({ (key): item }) %} + {% endif %} +{% endfor %} +{% set normalized_source_attr = normalized_source_attr|merge({ + name: source_name, + disabled: is_disabled, + required: required|default(false), +}) %} +{% set normalized_source_attr = source_id is not null + ? normalized_source_attr|merge({ id: source_id }) + : normalized_source_attr +%} {% set preferred_choices_flat = preferred_choices | map(choice => choice.choices is defined ? choice.choices : [choice]) | reduce((carry, choices) => carry|merge(choices), []) @@ -113,12 +142,14 @@ {% if can_use_ds %} {% set ds_dropdown_props = { - name: name|default('dropdown'), + name: source_name, items: ds_items, value: ds_value, disabled: is_disabled, maxVisibleItems: max_visible_items, class: class|default(''), + source: source, + sourceAttributes: normalized_source_attr, } %} {% set ds_dropdown_props = translated_placeholder is not same as(null) ? ds_dropdown_props|merge({ placeholder: translated_placeholder }) diff --git a/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig b/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig index d4e35a50de..8ba090d083 100644 --- a/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/form_fields/dropdown_widget.html.twig @@ -11,10 +11,14 @@ {% include '@ibexadesign/ui/component/dropdown/dropdown_ds.html.twig' with { source: source, + source_id: form.vars.id, + source_name: full_name, + source_attr: attr, choices: choices, preferred_choices: preferred_choices, value: form.vars.value, multiple: form.vars.multiple, + required: required, custom_init: attr.dropdown_custom_init|default(false), class: attr.dropdown_class|default(''), translation_domain: choice_translation_domain|default(false), From 42959111b364ece985bb5e5802246b11ced6a157 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Fri, 27 Mar 2026 13:18:58 +0100 Subject: [PATCH 11/30] IBX-11506: Initialize DS components in admin UI --- src/bundle/Resources/encore/ibexa.js.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bundle/Resources/encore/ibexa.js.config.js b/src/bundle/Resources/encore/ibexa.js.config.js index b12c548364..fa89300555 100644 --- a/src/bundle/Resources/encore/ibexa.js.config.js +++ b/src/bundle/Resources/encore/ibexa.js.config.js @@ -53,6 +53,7 @@ const layout = [ path.resolve(__dirname, '../public/js/scripts/admin.focus.mode.js'), path.resolve(__dirname, '../public/js/scripts/sidebar/main.menu.js'), path.resolve(__dirname, '../public/js/scripts/admin.input.text.js'), + path.resolve('./vendor/ibexa/design-system-twig/src/bundle/Resources/public/ts/init_components.ts'), path.resolve(__dirname, '../public/js/scripts/admin.table.js'), path.resolve(__dirname, '../public/js/scripts/core/collapse.js'), path.resolve(__dirname, '../public/js/scripts/admin.dropdown.js'), From 0e03da270075f78925afdefefd3dbed5efd736c1 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Sun, 10 May 2026 11:46:43 +0200 Subject: [PATCH 12/30] Revert "IBX-11506: Initialize DS components in admin UI" This reverts commit 9eaad2c23f09330ffe8e220274f0a053f1f71541. --- src/bundle/Resources/encore/ibexa.js.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bundle/Resources/encore/ibexa.js.config.js b/src/bundle/Resources/encore/ibexa.js.config.js index fa89300555..b12c548364 100644 --- a/src/bundle/Resources/encore/ibexa.js.config.js +++ b/src/bundle/Resources/encore/ibexa.js.config.js @@ -53,7 +53,6 @@ const layout = [ path.resolve(__dirname, '../public/js/scripts/admin.focus.mode.js'), path.resolve(__dirname, '../public/js/scripts/sidebar/main.menu.js'), path.resolve(__dirname, '../public/js/scripts/admin.input.text.js'), - path.resolve('./vendor/ibexa/design-system-twig/src/bundle/Resources/public/ts/init_components.ts'), path.resolve(__dirname, '../public/js/scripts/admin.table.js'), path.resolve(__dirname, '../public/js/scripts/core/collapse.js'), path.resolve(__dirname, '../public/js/scripts/admin.dropdown.js'), From ea20748e92a4aaf532dbc00ef7fc1dff131174f2 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Sun, 10 May 2026 12:04:56 +0200 Subject: [PATCH 13/30] fix: support small DS dropdown wrappers --- .../themes/admin/ui/component/dropdown/dropdown_ds.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index ea6464ad66..062cd7ea90 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -132,7 +132,6 @@ or is_selector|default(false) or has_items_class or has_items_list_header - or is_small|default(false) or is_ghost|default(false) or has_min_search_items or has_min_item_width @@ -148,6 +147,7 @@ disabled: is_disabled, maxVisibleItems: max_visible_items, class: class|default(''), + size: is_small|default(false) ? 'small' : 'medium', source: source, sourceAttributes: normalized_source_attr, } %} From 07dc1cab8bbe56b53313b1e5cdfab33d13186457 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Sun, 10 May 2026 13:56:46 +0200 Subject: [PATCH 14/30] fix: keep small dropdowns on legacy renderer --- .../themes/admin/ui/component/dropdown/dropdown_ds.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 062cd7ea90..ea6464ad66 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -132,6 +132,7 @@ or is_selector|default(false) or has_items_class or has_items_list_header + or is_small|default(false) or is_ghost|default(false) or has_min_search_items or has_min_item_width @@ -147,7 +148,6 @@ disabled: is_disabled, maxVisibleItems: max_visible_items, class: class|default(''), - size: is_small|default(false) ? 'small' : 'medium', source: source, sourceAttributes: normalized_source_attr, } %} From aad8208ea964cfbd0fddafacc82a9995629eb177 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 12:41:34 +0200 Subject: [PATCH 15/30] refactor --- .../component/dropdown/dropdown_ds.html.twig | 104 ++++++------------ 1 file changed, 34 insertions(+), 70 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index ea6464ad66..111a33612c 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -34,64 +34,6 @@ ? normalized_source_attr|merge({ id: source_id }) : normalized_source_attr %} -{% set preferred_choices_flat = preferred_choices - | map(choice => choice.choices is defined ? choice.choices : [choice]) - | reduce((carry, choices) => carry|merge(choices), []) -%} -{% set choices_flat = choices - | map(choice => choice.choices is defined ? choice.choices : [choice]) - | reduce((carry, choices) => carry|merge(choices), []) -%} - -{% set normalized_preferred_choices = preferred_choices - | map(choice => choice.choices is defined - ? choice.choices|map(child => { - value: child.value ~ '', - label: '[' - ~ (translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain)) - ~ ']: ' - ~ (translation_domain is same as(false) ? child.label : child.label|trans({}, translation_domain)), - }) - : [{ - value: choice.value ~ '', - label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), - }] - ) - | reduce((carry, choices) => carry|merge(choices), []) -%} -{% set normalized_choices = choices - | map(choice => choice.choices is defined - ? choice.choices|map(child => { - value: child.value ~ '', - label: '[' - ~ (translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain)) - ~ ']: ' - ~ (translation_domain is same as(false) ? child.label : child.label|trans({}, translation_domain)), - }) - : [{ - value: choice.value ~ '', - label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), - }] - ) - | reduce((carry, choices) => carry|merge(choices), []) -%} -{% set normalized_choices_data = normalized_preferred_choices - | merge(normalized_choices) - | reduce((carry, choice) => choice.value in carry.values - ? carry - : { - items: carry.items|merge([choice]), - values: carry.values|merge([choice.value]), - }, { - items: [], - values: [], - }) -%} -{% set normalized_items = normalized_choices_data.items %} -{% set has_icons = item_icon is defined - or preferred_choices_flat|filter(choice => choice.icon is defined)|length > 0 - or choices_flat|filter(choice => choice.icon is defined)|length > 0 -%} {% set translated_placeholder = placeholder is defined and placeholder is not none ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) : null @@ -101,18 +43,7 @@ ? translated_placeholder|trim|default(empty_placeholder_fallback) : null %} -{% set normalized_ds_items = normalized_items|map(choice => { - id: choice.value, - label: choice.label, -}) %} -{% set ds_items = not multiple and translated_placeholder is not same as(null) - ? [{ id: '', label: empty_placeholder_label }]|merge(normalized_ds_items) - : normalized_ds_items -%} -{% set ds_value = multiple - ? (value is iterable ? value|map(item => item ~ '') : []) - : (value is not null ? value ~ '' : '') -%} + {% set has_selected_item_template_path = selected_item_template_path is defined and selected_item_template_path is not null %} {% set has_list_item_template_path = list_item_template_path is defined and list_item_template_path is not null %} {% set has_selected_item_label = selected_item_label is defined and selected_item_label is not empty %} @@ -123,6 +54,7 @@ {% set has_min_item_width = min_item_width is defined and min_item_width is not null %} {% set has_grouped_preferred_choices = preferred_choices|filter(choice => choice.choices is defined)|length > 0 %} {% set has_grouped_choices = choices|filter(choice => choice.choices is defined)|length > 0 %} + {% set can_use_ds = not ( custom_init or has_selected_item_template_path @@ -141,6 +73,38 @@ ) %} {% if can_use_ds %} + {% set normalized_preferred_choices = preferred_choices|map(choice => { + value: choice.value ~ '', + label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), + }) %} + {% set normalized_choices = choices|map(choice => { + value: choice.value ~ '', + label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), + }) %} + {% set normalized_items = normalized_preferred_choices + | merge(normalized_choices) + | reduce((carry, choice) => choice.value in carry.values + ? carry + : { + items: carry.items|merge([choice]), + values: carry.values|merge([choice.value]), + }, { + items: [], + values: [], + }) + %} + {% set normalized_ds_items = normalized_items.items|map(choice => { + id: choice.value, + label: choice.label, + }) %} + {% set ds_items = not multiple and translated_placeholder is not same as(null) + ? [{ id: '', label: empty_placeholder_label }]|merge(normalized_ds_items) + : normalized_ds_items + %} + {% set ds_value = multiple + ? (value is iterable ? value|map(item => item ~ '') : []) + : (value is not null ? value ~ '' : '') + %} {% set ds_dropdown_props = { name: source_name, items: ds_items, From 56774cbde088f441fef51bc85effc31ee670faa8 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 14:04:02 +0200 Subject: [PATCH 16/30] fix: toggle matching dropdown disabled class --- .../public/js/scripts/admin.location.add.custom_url.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js b/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js index 3766be2f01..b271b85ea8 100644 --- a/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js +++ b/src/bundle/Resources/public/js/scripts/admin.location.add.custom_url.js @@ -21,9 +21,11 @@ const siteAccessSelect = modal.querySelector('.ibexa-custom-url-from__item--siteacces .ibexa-dropdown, .ibexa-custom-url-from__item--siteacces .ids-dropdown'); const sourceSelect = siteAccessSelect?.querySelector('.ibexa-input--select, .ids-dropdown__source select'); - siteAccessSelect?.classList.toggle('ibexa-dropdown--is-disabled', isChecked); - siteAccessSelect?.classList.toggle('ibexa-dropdown--disabled', isChecked); - siteAccessSelect?.classList.toggle('ids-dropdown--disabled', isChecked); + if (siteAccessSelect?.classList.contains('ibexa-dropdown')) { + siteAccessSelect.classList.toggle('ibexa-dropdown--disabled', isChecked); + } else if (siteAccessSelect?.classList.contains('ids-dropdown')) { + siteAccessSelect.classList.toggle('ids-dropdown--disabled', isChecked); + } if (sourceSelect) { sourceSelect.disabled = isChecked; From 4977b3c99d5ada8fc9d88ef9ede3521460f249af Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 14:26:08 +0200 Subject: [PATCH 17/30] refactor: simplify dropdown compatibility helpers --- .../js/scripts/admin.notifications.filters.js | 11 +++++---- .../public/js/scripts/admin.search.filters.js | 24 ++++++++++++------- .../component/dropdown/dropdown_ds.html.twig | 1 + 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js b/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js index 594de83356..70b8320398 100644 --- a/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js +++ b/src/bundle/Resources/public/js/scripts/admin.notifications.filters.js @@ -1,5 +1,4 @@ (function (global, doc) { - const SELECTOR_DROPDOWN_SOURCE_SELECT = '.ibexa-dropdown__source .ibexa-input--select, .ids-dropdown__source select'; const searchForm = doc.querySelector('.ibexa-list-search-form'); const filtersContainerNode = doc.querySelector('.ibexa-list-filters'); const applyFiltersBtn = filtersContainerNode.querySelector('.ibexa-btn--apply'); @@ -13,7 +12,9 @@ return; } - const sourceSelect = filterNode.querySelector(`.ibexa-list-filters__item-content ${SELECTOR_DROPDOWN_SOURCE_SELECT}`); + const sourceSelect = filterNode.querySelector( + '.ibexa-list-filters__item-content .ibexa-dropdown__source .ibexa-input--select, .ibexa-list-filters__item-content .ids-dropdown__source select', + ); const checkboxes = filterNode.querySelectorAll( '.ibexa-list-filters__item-content .ibexa-input--checkbox:not([name="dropdown-checkbox"])', ); @@ -58,7 +59,9 @@ return; } - const sourceSelect = filterNode.querySelector(`.ibexa-list-filters__item-content ${SELECTOR_DROPDOWN_SOURCE_SELECT}`); + const sourceSelect = filterNode.querySelector( + '.ibexa-list-filters__item-content .ibexa-dropdown__source .ibexa-input--select, .ibexa-list-filters__item-content .ids-dropdown__source select', + ); sourceSelect?.addEventListener('change', filterChange, false); }; @@ -80,7 +83,7 @@ return; } - const select = filterNode.querySelector(SELECTOR_DROPDOWN_SOURCE_SELECT); + const select = filterNode.querySelector('.ibexa-dropdown__source .ibexa-input--select, .ids-dropdown__source select'); const checkedCheckboxes = filterNode.querySelectorAll('.ibexa-input--checkbox:checked'); if (isNodeDatePicker(filterNode)) { diff --git a/src/bundle/Resources/public/js/scripts/admin.search.filters.js b/src/bundle/Resources/public/js/scripts/admin.search.filters.js index 71f405a3c2..6959eda4af 100644 --- a/src/bundle/Resources/public/js/scripts/admin.search.filters.js +++ b/src/bundle/Resources/public/js/scripts/admin.search.filters.js @@ -2,21 +2,23 @@ const { escapeHTML, escapeHTMLAttribute } = ibexa.helpers.text; const { dangerouslySetInnerHTML } = ibexa.helpers.dom; const { getInstance } = ibexa.helpers.objectInstances; - const SELECTOR_DROPDOWN = '.ibexa-dropdown, .ids-dropdown'; - const SELECTOR_DROPDOWN_SOURCE_SELECT = '.ibexa-input--select, .ids-dropdown__source select'; let getUsersTimeout; const SELECTOR_TAG = '.ibexa-tag'; const token = doc.querySelector('meta[name="CSRF-Token"]').content; const siteaccess = doc.querySelector('meta[name="SiteAccess"]').content; const filters = doc.querySelector('.ibexa-filters'); - const getDropdownContainer = (selector) => filters.querySelector(`${selector} ${SELECTOR_DROPDOWN}`); - const getDropdownSourceSelect = (selector) => filters.querySelector(`${selector} ${SELECTOR_DROPDOWN_SOURCE_SELECT}`); const clearBtn = filters.querySelector('.ibexa-btn--clear'); const applyBtn = filters.querySelector('.ibexa-btn--apply'); const contentTypeSelect = doc.querySelector('.ibexa-filters__item--content-type .ibexa-filters__select'); - const sectionSelect = getDropdownSourceSelect('.ibexa-filters__item--section'); - const lastModifiedDropdownNode = getDropdownContainer('.ibexa-filters__item--modified'); - const lastModifiedSelectNode = getDropdownSourceSelect('.ibexa-filters__item--modified'); + const sectionSelect = filters.querySelector( + '.ibexa-filters__item--section .ibexa-input--select, .ibexa-filters__item--section .ids-dropdown__source select', + ); + const lastModifiedDropdownNode = filters.querySelector( + '.ibexa-filters__item--modified .ibexa-dropdown, .ibexa-filters__item--modified .ids-dropdown', + ); + const lastModifiedSelectNode = filters.querySelector( + '.ibexa-filters__item--modified .ibexa-input--select, .ibexa-filters__item--modified .ids-dropdown__source select', + ); const lastModifiedSelect = getInstance(lastModifiedDropdownNode); const lastModifiedDateRangeNode = doc.querySelector('.ibexa-filters__item--modified .ibexa-date-time-range-single'); const lastModifiedDateRange = getInstance(lastModifiedDateRangeNode); @@ -28,8 +30,12 @@ const lastModifiedPeriod = doc.querySelector(lastModifiedPeriodSelector); const lastModifiedStartDate = doc.querySelector(lastModifiedStartSelector); const lastModifiedEndDate = doc.querySelector(lastModifiedEndSelector); - const lastCreatedDropdownNode = getDropdownContainer('.ibexa-filters__item--created'); - const lastCreatedSelectNode = getDropdownSourceSelect('.ibexa-filters__item--created'); + const lastCreatedDropdownNode = filters.querySelector( + '.ibexa-filters__item--created .ibexa-dropdown, .ibexa-filters__item--created .ids-dropdown', + ); + const lastCreatedSelectNode = filters.querySelector( + '.ibexa-filters__item--created .ibexa-input--select, .ibexa-filters__item--created .ids-dropdown__source select', + ); const lastCreatedSelect = getInstance(lastCreatedDropdownNode); const lastCreatedDateRangeNode = doc.querySelector('.ibexa-filters__item--created .ibexa-date-time-range-single'); const lastCreatedDateRange = getInstance(lastCreatedDateRangeNode); diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 111a33612c..bd7cc652e4 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -4,6 +4,7 @@ {% set multiple = multiple|default(false) %} {% set custom_init = custom_init|default(false) %} {% set is_disabled = is_disabled|default(false) or attr.readonly|default(false) %} + {% set source = source|default(null) %} {% set source_attr = source_attr|default({}) %} {% set source_id = source_id|default(source_attr.id|default(null)) %} From bfcb1b4e00ba0a2146ee43ea91ae045932705eae Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 14:31:27 +0200 Subject: [PATCH 18/30] refactor: drop unused source attr exclusions --- .../ui/component/dropdown/dropdown_ds.html.twig | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index bd7cc652e4..6577a2f4cb 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -10,21 +10,9 @@ {% set source_id = source_id|default(source_attr.id|default(null)) %} {% set source_name = source_name|default(source_attr.name|default(name|default('dropdown'))) %} {% set max_visible_items = 5 %} -{% set excluded_source_attr_keys = [ - 'dropdown_hidden', - 'dropdown_class', - 'dropdown_custom_init', - 'is_small', - 'is_ghost', - 'is_selector', - 'is_dynamic', - 'has_select_all_toggler', -] %} {% set normalized_source_attr = {} %} {% for key, item in source_attr %} - {% if key not in excluded_source_attr_keys %} - {% set normalized_source_attr = normalized_source_attr|merge({ (key): item }) %} - {% endif %} + {% set normalized_source_attr = normalized_source_attr|merge({ (key): item }) %} {% endfor %} {% set normalized_source_attr = normalized_source_attr|merge({ name: source_name, From fafeefa84f8cd2d91843e8e2d95847c1f2b29675 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 14:33:16 +0200 Subject: [PATCH 19/30] refactor: tighten DS dropdown bridge setup --- .../admin/ui/component/dropdown/dropdown_ds.html.twig | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 6577a2f4cb..dbb334d238 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -9,12 +9,7 @@ {% set source_attr = source_attr|default({}) %} {% set source_id = source_id|default(source_attr.id|default(null)) %} {% set source_name = source_name|default(source_attr.name|default(name|default('dropdown'))) %} -{% set max_visible_items = 5 %} -{% set normalized_source_attr = {} %} -{% for key, item in source_attr %} - {% set normalized_source_attr = normalized_source_attr|merge({ (key): item }) %} -{% endfor %} -{% set normalized_source_attr = normalized_source_attr|merge({ +{% set normalized_source_attr = source_attr|merge({ name: source_name, disabled: is_disabled, required: required|default(false), @@ -62,6 +57,7 @@ ) %} {% if can_use_ds %} + {% set max_visible_items = 5 %} {% set normalized_preferred_choices = preferred_choices|map(choice => { value: choice.value ~ '', label: translation_domain is same as(false) ? choice.label : choice.label|trans({}, translation_domain), From f07184888774ce528886ac676487f5d261a10e72 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 14:46:12 +0200 Subject: [PATCH 20/30] refactor: simplify dropdown bridge context maps --- .../component/dropdown/dropdown_ds.html.twig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index dbb334d238..82fa542963 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -97,7 +97,7 @@ disabled: is_disabled, maxVisibleItems: max_visible_items, class: class|default(''), - source: source, + source, sourceAttributes: normalized_source_attr, } %} {% set ds_dropdown_props = translated_placeholder is not same as(null) @@ -116,16 +116,16 @@ {% endif %} {% else %} {% set legacy_context = { - source: source|default(null), - choices: choices, - preferred_choices: preferred_choices, - value: value, - multiple: multiple, - custom_init: custom_init, + source, + choices, + preferred_choices, + value, + multiple, + custom_init, class: class|default(''), - translation_domain: translation_domain, + translation_domain, custom_form: custom_form is defined ? custom_form : true, - is_disabled: is_disabled, + is_disabled, is_hidden: is_hidden|default(false), is_small: is_small|default(false), is_ghost: is_ghost|default(false), From e49c4fa40973878b5c0145c73d139272d682c6a7 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Mon, 11 May 2026 14:53:46 +0200 Subject: [PATCH 21/30] fix: address design system provider lint issues --- .../modules/common/design-system/design.system.provider.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js b/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js index ef38ea08fa..aa6af3c473 100644 --- a/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js +++ b/src/bundle/ui-dev/src/modules/common/design-system/design.system.provider.js @@ -1,4 +1,5 @@ import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; import { AssetsProvider, TranslatorProvider } from '@ids-components/context'; @@ -15,7 +16,7 @@ const DesignSystemProvider = ({ children }) => { ); const translatorContextValue = useMemo( () => ({ - trans: (key, parameters = {}, domain) => Translator.trans(key, parameters, domain), + trans: (key, parameters, domain) => Translator.trans(key, parameters ?? {}, domain), }), [Translator], ); @@ -27,4 +28,8 @@ const DesignSystemProvider = ({ children }) => { ); }; +DesignSystemProvider.propTypes = { + children: PropTypes.node.isRequired, +}; + export default DesignSystemProvider; From 35c11fed355fe1cbc40554edaca479f5d4df1dcb Mon Sep 17 00:00:00 2001 From: tischsoic Date: Thu, 12 Mar 2026 10:30:45 +0100 Subject: [PATCH 22/30] DST in composer.json --- composer.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 97beea181e..e34fc9058c 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,7 @@ "ibexa/content-forms": "~6.0.x-dev", "ibexa/core": "~6.0.x-dev", "ibexa/design-engine": "~6.0.x-dev", + "ibexa/design-system-twig": "~6.0.x-dev", "ibexa/rest": "~6.0.x-dev", "ibexa/search": "~6.0.x-dev", "ibexa/twig-components": "~6.0.x-dev", @@ -97,5 +98,11 @@ "branch-alias": { "dev-main": "6.0.x-dev" } - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/ibexa/design-system-twig" + } + ] } From da1844b82d8e5b755660fbc8afe145b40392a94b Mon Sep 17 00:00:00 2001 From: tischsoic Date: Tue, 9 Jun 2026 13:58:55 +0200 Subject: [PATCH 23/30] fix: support DS translation modal dropdowns --- .../public/js/scripts/admin.location.add.translation.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.location.add.translation.js b/src/bundle/Resources/public/js/scripts/admin.location.add.translation.js index f63ae54c3e..8dc6ddef27 100644 --- a/src/bundle/Resources/public/js/scripts/admin.location.add.translation.js +++ b/src/bundle/Resources/public/js/scripts/admin.location.add.translation.js @@ -18,12 +18,16 @@ }; doc.querySelectorAll('.ibexa-translation__language-wrapper--language').forEach((select) => { - const dropdown = select.closest('.ibexa-dropdown'); + const dropdown = select.closest('.ibexa-dropdown, .ids-dropdown'); const observer = new MutationObserver(() => toggleBtnDisabledState(select)); toggleBtnDisabledState(select); select.addEventListener('change', ({ target }) => toggleBtnDisabledState(target), false); + if (!dropdown) { + return; + } + observer.observe(dropdown, observerConfig); }); })(window, window.document); From 7d5ff4f44723a48b7f39848e0aaf370dd87c579a Mon Sep 17 00:00:00 2001 From: KamilSznajdrowicz Date: Wed, 10 Jun 2026 11:31:52 +0200 Subject: [PATCH 24/30] Fix discount behat test selectors aftrer DS update --- src/lib/Behat/Component/CreateNewPopup.php | 4 ++-- src/lib/Behat/Component/IbexaDropdown.php | 8 ++++---- src/lib/Behat/Component/TranslationDialog.php | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/Behat/Component/CreateNewPopup.php b/src/lib/Behat/Component/CreateNewPopup.php index fcf26c7a29..c6f6cc432c 100644 --- a/src/lib/Behat/Component/CreateNewPopup.php +++ b/src/lib/Behat/Component/CreateNewPopup.php @@ -79,9 +79,9 @@ protected function specifyLocators(): array new VisibleCSSLocator('cancelButton', '.ibexa-extra-actions__pre-form-btns .ibexa-btn--secondary'), new VisibleCSSLocator('popup', '.ibexa-extra-actions:not(.ibexa-extra-actions--hidden)'), new VisibleCSSLocator('formGroup', '.form-group'), - new VisibleCSSLocator('dropdown', '.ibexa-dropdown'), + new VisibleCSSLocator('dropdown', '.ids-dropdown'), new VisibleCSSLocator('label', '.ibexa-label'), - new VisibleCSSLocator('dropdownValue', '.ibexa-dropdown__selection-info'), + new VisibleCSSLocator('dropdownValue', '.ids-dropdown__widget'), new VisibleCSSLocator('radioValue', '.ibexa-dc-extra-actions-applies-to__option'), new VisibleCSSLocator('radioLabel', '.ibexa-label--checkbox-radio'), ]; diff --git a/src/lib/Behat/Component/IbexaDropdown.php b/src/lib/Behat/Component/IbexaDropdown.php index c1fad443b2..02b66c027f 100644 --- a/src/lib/Behat/Component/IbexaDropdown.php +++ b/src/lib/Behat/Component/IbexaDropdown.php @@ -21,15 +21,15 @@ public function verifyIsLoaded(): void { $this->getHTMLPage() ->setTimeout(5) - ->waitUntilCondition(new ElementTransitionHasEndedCondition($this->getHTMLPage(), $this->getLocator('isIbexaDropdownVisible'))); + ->waitUntilCondition(new ElementExistsCondition($this->getHTMLPage(), $this->getLocator('isIbexaDropdownVisible'))); } protected function specifyLocators(): array { return [ - new VisibleCSSLocator('ibexaDropdownExtended', '.ibexa-dropdown-popover .ibexa-dropdown__items .ibexa-dropdown__item'), - new VisibleCSSLocator('ibexaDropdownLabel', '.ibexa-dropdown__item-label'), - new VisibleCSSLocator('isIbexaDropdownVisible', '.ibexa-dropdown-popover'), + new VisibleCSSLocator('ibexaDropdownExtended', '.ids-dropdown__items-container .ids-dropdown__items .ids-dropdown__item'), + new VisibleCSSLocator('ibexaDropdownLabel', '.ids-dropdown__item'), + new VisibleCSSLocator('isIbexaDropdownVisible', '.ids-dropdown__items-container'), ]; } diff --git a/src/lib/Behat/Component/TranslationDialog.php b/src/lib/Behat/Component/TranslationDialog.php index dd3111d6a3..dcff47969b 100644 --- a/src/lib/Behat/Component/TranslationDialog.php +++ b/src/lib/Behat/Component/TranslationDialog.php @@ -44,8 +44,8 @@ public function verifyIsLoaded(): void protected function specifyLocators(): array { return array_merge(parent::specifyLocators(), [ - new VisibleCSSLocator('expandNewTranslationDropdown', '#add-translation-modal [for="add-translation_language"] + .ibexa-dropdown .ibexa-dropdown__selection-info'), - new VisibleCSSLocator('expandBaseTranslationDropdown', '#add-translation-modal [for="add-translation_base_language"] + .ibexa-dropdown .ibexa-dropdown__selection-info'), + new VisibleCSSLocator('expandNewTranslationDropdown', '#add-translation-modal [for="add-translation_language"] + .ids-dropdown .ids-dropdown__selection-info'), + new VisibleCSSLocator('expandBaseTranslationDropdown', '#add-translation-modal [for="add-translation_base_language"] + .ids-dropdown .ids-dropdown__selection-info'), new VisibleCSSLocator('addTranslationPopupModalTitle', '#add-translation-modal .modal-title'), ]); } From 482f1c74209ab62d76ddee6b102e7901e8ab3ceb Mon Sep 17 00:00:00 2001 From: KamilSznajdrowicz Date: Wed, 10 Jun 2026 15:10:46 +0200 Subject: [PATCH 25/30] Make dropdown selectors compatible with legacy and DS --- src/lib/Behat/Component/CreateNewPopup.php | 4 ++-- src/lib/Behat/Component/IbexaDropdown.php | 6 +++--- src/lib/Behat/Component/TranslationDialog.php | 4 ++-- src/lib/Behat/Page/RoleUpdatePage.php | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/Behat/Component/CreateNewPopup.php b/src/lib/Behat/Component/CreateNewPopup.php index c6f6cc432c..e113209f29 100644 --- a/src/lib/Behat/Component/CreateNewPopup.php +++ b/src/lib/Behat/Component/CreateNewPopup.php @@ -79,9 +79,9 @@ protected function specifyLocators(): array new VisibleCSSLocator('cancelButton', '.ibexa-extra-actions__pre-form-btns .ibexa-btn--secondary'), new VisibleCSSLocator('popup', '.ibexa-extra-actions:not(.ibexa-extra-actions--hidden)'), new VisibleCSSLocator('formGroup', '.form-group'), - new VisibleCSSLocator('dropdown', '.ids-dropdown'), + new VisibleCSSLocator('dropdown', '.ibexa-dropdown, .ids-dropdown'), new VisibleCSSLocator('label', '.ibexa-label'), - new VisibleCSSLocator('dropdownValue', '.ids-dropdown__widget'), + new VisibleCSSLocator('dropdownValue', '.ibexa-dropdown__selection-info, .ids-dropdown__widget'), new VisibleCSSLocator('radioValue', '.ibexa-dc-extra-actions-applies-to__option'), new VisibleCSSLocator('radioLabel', '.ibexa-label--checkbox-radio'), ]; diff --git a/src/lib/Behat/Component/IbexaDropdown.php b/src/lib/Behat/Component/IbexaDropdown.php index 02b66c027f..dd94adc48d 100644 --- a/src/lib/Behat/Component/IbexaDropdown.php +++ b/src/lib/Behat/Component/IbexaDropdown.php @@ -27,9 +27,9 @@ public function verifyIsLoaded(): void protected function specifyLocators(): array { return [ - new VisibleCSSLocator('ibexaDropdownExtended', '.ids-dropdown__items-container .ids-dropdown__items .ids-dropdown__item'), - new VisibleCSSLocator('ibexaDropdownLabel', '.ids-dropdown__item'), - new VisibleCSSLocator('isIbexaDropdownVisible', '.ids-dropdown__items-container'), + new VisibleCSSLocator('ibexaDropdownExtended', '.ibexa-dropdown-popover .ibexa-dropdown__items .ibexa-dropdown__item, .ids-dropdown__items-container .ids-dropdown__items .ids-dropdown__item'), + new VisibleCSSLocator('ibexaDropdownLabel', '.ibexa-dropdown__item-label, .ids-dropdown__item'), + new VisibleCSSLocator('isIbexaDropdownVisible', '.ibexa-dropdown-popover, .ids-dropdown__items-container'), ]; } diff --git a/src/lib/Behat/Component/TranslationDialog.php b/src/lib/Behat/Component/TranslationDialog.php index dcff47969b..d2dae9fcc7 100644 --- a/src/lib/Behat/Component/TranslationDialog.php +++ b/src/lib/Behat/Component/TranslationDialog.php @@ -44,8 +44,8 @@ public function verifyIsLoaded(): void protected function specifyLocators(): array { return array_merge(parent::specifyLocators(), [ - new VisibleCSSLocator('expandNewTranslationDropdown', '#add-translation-modal [for="add-translation_language"] + .ids-dropdown .ids-dropdown__selection-info'), - new VisibleCSSLocator('expandBaseTranslationDropdown', '#add-translation-modal [for="add-translation_base_language"] + .ids-dropdown .ids-dropdown__selection-info'), + new VisibleCSSLocator('expandNewTranslationDropdown', '#add-translation-modal [for="add-translation_language"] + .ibexa-dropdown .ibexa-dropdown__selection-info, #add-translation-modal [for="add-translation_language"] + .ids-dropdown .ids-dropdown__selection-info'), + new VisibleCSSLocator('expandBaseTranslationDropdown', '#add-translation-modal [for="add-translation_base_language"] + .ibexa-dropdown .ibexa-dropdown__selection-info, #add-translation-modal [for="add-translation_base_language"] + .ids-dropdown .ids-dropdown__selection-info'), new VisibleCSSLocator('addTranslationPopupModalTitle', '#add-translation-modal .modal-title'), ]); } diff --git a/src/lib/Behat/Page/RoleUpdatePage.php b/src/lib/Behat/Page/RoleUpdatePage.php index 48941f2352..33bfee639c 100644 --- a/src/lib/Behat/Page/RoleUpdatePage.php +++ b/src/lib/Behat/Page/RoleUpdatePage.php @@ -82,12 +82,12 @@ public function specifyLocators(): array parent::specifyLocators(), [ new VisibleCSSLocator('limitationField', '.ibexa-update-policy__action-wrapper'), - new VisibleCSSLocator('limitationDropdown', '.ibexa-dropdown__selection-info'), - new VisibleCSSLocator('limitationDropdownOption', '.ibexa-dropdown-popover .ibexa-dropdown__items .ibexa-dropdown__item'), - new VisibleCSSLocator('limitationDropdownOptionRemove', '.ibexa-dropdown__remove-selection'), + new VisibleCSSLocator('limitationDropdown', '.ibexa-dropdown__selection-info, .ids-dropdown__selection-info'), + new VisibleCSSLocator('limitationDropdownOption', '.ibexa-dropdown-popover .ibexa-dropdown__items .ibexa-dropdown__item, .ids-dropdown__items-container .ids-dropdown__items .ids-dropdown__item'), + new VisibleCSSLocator('limitationDropdownOptionRemove', '.ibexa-dropdown__remove-selection, .ids-chip__delete'), new VisibleCSSLocator('labelSelector', '.ibexa-label'), new VisibleCSSLocator('policyAssignmentSelect', '#role_assignment_create_limitation_type_section'), - new VisibleCSSLocator('ibexaDropdownSelectionInfo', 'div.ibexa-dropdown__wrapper > ul.ibexa-dropdown__selection-info'), + new VisibleCSSLocator('ibexaDropdownSelectionInfo', 'div.ibexa-dropdown__wrapper > ul.ibexa-dropdown__selection-info, div.ids-dropdown__widget > .ids-dropdown__selection-info'), new VisibleCSSLocator('newPolicySelectList', '#policy_create_policy'), ] ); From f7dd27b303f960c37b1893ea19f352716048f242 Mon Sep 17 00:00:00 2001 From: KamilSznajdrowicz Date: Wed, 10 Jun 2026 18:56:51 +0200 Subject: [PATCH 26/30] Fix-cs and others selectors --- src/lib/Behat/Component/ContentTypePicker.php | 2 +- src/lib/Behat/Component/IbexaDropdown.php | 1 - src/lib/Behat/Page/UserSettingsPage.php | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/Behat/Component/ContentTypePicker.php b/src/lib/Behat/Component/ContentTypePicker.php index ba18733435..5811aae0da 100644 --- a/src/lib/Behat/Component/ContentTypePicker.php +++ b/src/lib/Behat/Component/ContentTypePicker.php @@ -73,7 +73,7 @@ protected function specifyLocators(): array new VisibleCSSLocator('filterInput', '.ibexa-content-menu-wrapper .ibexa-extra-actions__section-content--content-type .ibexa-instant-filter__input, .c-udw-tab .ibexa-extra-actions__section-content--content-type .ibexa-instant-filter__input'), new VisibleCSSLocator('contentTypeItem', '.ibexa-content-menu-wrapper .ibexa-extra-actions__section-content--content-type .ibexa-instant-filter__group-item:not([hidden]) .form-check-label, .c-udw-tab .ibexa-extra-actions__section-content--content-type .ibexa-instant-filter__group-item:not([hidden]) .form-check-label'), new VisibleCSSLocator('header', '.ibexa-content-menu-wrapper .ibexa-extra-actions--create .ibexa-extra-actions__header h2'), - new VisibleCSSLocator('languageDropdown', '.ibexa-content-menu-wrapper .ibexa-dropdown__selection-info'), + new VisibleCSSLocator('languageDropdown', '.ibexa-content-menu-wrapper .ibexa-dropdown__selection-info, .ibexa-content-menu-wrapper .ids-dropdown__selection-info'), new VisibleCSSLocator('createButton', '.c-content-create__confirm-button, [id="content_create_create"]'), ]; } diff --git a/src/lib/Behat/Component/IbexaDropdown.php b/src/lib/Behat/Component/IbexaDropdown.php index dd94adc48d..3f90899b4b 100644 --- a/src/lib/Behat/Component/IbexaDropdown.php +++ b/src/lib/Behat/Component/IbexaDropdown.php @@ -10,7 +10,6 @@ use Ibexa\Behat\Browser\Component\Component; use Ibexa\Behat\Browser\Element\Condition\ElementExistsCondition; -use Ibexa\Behat\Browser\Element\Condition\ElementTransitionHasEndedCondition; use Ibexa\Behat\Browser\Element\Criterion\ElementTextCriterion; use Ibexa\Behat\Browser\Element\Criterion\ElementTextFragmentCriterion; use Ibexa\Behat\Browser\Locator\VisibleCSSLocator; diff --git a/src/lib/Behat/Page/UserSettingsPage.php b/src/lib/Behat/Page/UserSettingsPage.php index 8f62180b78..d18d62f7c2 100644 --- a/src/lib/Behat/Page/UserSettingsPage.php +++ b/src/lib/Behat/Page/UserSettingsPage.php @@ -55,9 +55,9 @@ protected function specifyLocators(): array return [ new VisibleCSSLocator('button', '.ibexa-btn'), new VisibleCSSLocator('title', '.ibexa-edit-header__title,.ibexa-page-title__content'), - new VisibleCSSLocator('autosaveDraftValueDropdown', '#user_setting_update_autosave div.ibexa-dropdown__wrapper > ul'), + new VisibleCSSLocator('autosaveDraftValueDropdown', '#user_setting_update_autosave div.ibexa-dropdown__wrapper > ul, #user_setting_update_autosave div.ids-dropdown__widget > .ids-dropdown__selection-info'), new VisibleCSSLocator('autosaveIntervalEdit', '#user_setting_update_autosave_interval_value'), - new VisibleCSSLocator('helpCenterValueDropdown', '#user_setting_update_help_center div.ibexa-dropdown__wrapper > ul'), + new VisibleCSSLocator('helpCenterValueDropdown', '#user_setting_update_help_center div.ibexa-dropdown__wrapper > ul, #user_setting_update_help_center div.ids-dropdown__widget > .ids-dropdown__selection-info'), ]; } From 6aa6998b7e1b096225b827e0bdb0e5072d31cd41 Mon Sep 17 00:00:00 2001 From: KamilSznajdrowicz Date: Thu, 11 Jun 2026 11:33:05 +0200 Subject: [PATCH 27/30] Make dropdown selectors compatible with DS --- features/standard/ContentType.feature | 3 ++- features/standard/fields/other.feature | 9 +++++---- src/lib/Behat/Component/CreateNewPopup.php | 2 +- src/lib/Behat/Component/CreateUrlAliasModal.php | 2 +- src/lib/Behat/Component/Fields/Country.php | 2 +- src/lib/Behat/Component/Fields/Selection.php | 6 +++--- src/lib/Behat/Component/TrashSearch.php | 2 +- src/lib/Behat/Page/ContentViewPage.php | 2 +- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/features/standard/ContentType.feature b/features/standard/ContentType.feature index 96938da21b..4aca9ea98d 100644 --- a/features/standard/ContentType.feature +++ b/features/standard/ContentType.feature @@ -74,7 +74,8 @@ Feature: Content types management @javascript Scenario: New content type can be added to content type group - Given I am logged as admin + Given I open Login page in admin SiteAccess + And I log in as "admin" with password "publish" And I'm on content type Page for "Content" group When I create a new content type And I set fields diff --git a/features/standard/fields/other.feature b/features/standard/fields/other.feature index 77f3b10330..5a1baea901 100644 --- a/features/standard/fields/other.feature +++ b/features/standard/fields/other.feature @@ -28,8 +28,8 @@ Feature: Content fields setting and editing | Field | | | Examples: - | fieldInternalName | fieldName | fieldSettings | label1 | value1 | contentItemName | fieldTypeIdentifier | - | ibexa_selection | Selection | is_multiple:false,options:A first-Bielefeld-TestValue-Turtles-Zombies | value | TestValue | TestValue | ibexa_selection | + | fieldInternalName | fieldName | fieldSettings | label1 | value1 | contentItemName | fieldTypeIdentifier | + | ibexa_selection | Selection | is_multiple:false,options:A first-Bielefeld-TestValue-Turtles-Zombies | value | TestValue | TestValue | ibexa_selection | | ibexa_boolean | Checkbox | | value | true | 1 | | | ibexa_email | Email address | | value | email@example.com | email@example.com | | | ibexa_float | Float | | value | 11.11 | 11.11 | | @@ -40,7 +40,8 @@ Feature: Content fields setting and editing @javascript @APIUser:admin Scenario Outline: Edit content item with given field - Given I am logged as admin + Given I open Login page in admin SiteAccess + And I log in as "admin" with password "publish" And I'm on Content view Page for "OtherFieldsContainer/" When I perform the "Edit" action And I set content fields @@ -55,7 +56,7 @@ Feature: Content fields setting and editing Examples: | label1 | value1 | oldContentItemName | newContentItemName | fieldTypeIdentifier | - | value | Bielefeld | TestValue | Bielefeld | ibexa_selection | + | value | Bielefeld | TestValue | Bielefeld | ibexa_selection | | value | false | 1 | 0 | | | value | edited.email@example.com | email@example.com | edited.email@example.com | | | value | 12.34 | 11.11 | 12.34 | | diff --git a/src/lib/Behat/Component/CreateNewPopup.php b/src/lib/Behat/Component/CreateNewPopup.php index e113209f29..ad6b19127a 100644 --- a/src/lib/Behat/Component/CreateNewPopup.php +++ b/src/lib/Behat/Component/CreateNewPopup.php @@ -81,7 +81,7 @@ protected function specifyLocators(): array new VisibleCSSLocator('formGroup', '.form-group'), new VisibleCSSLocator('dropdown', '.ibexa-dropdown, .ids-dropdown'), new VisibleCSSLocator('label', '.ibexa-label'), - new VisibleCSSLocator('dropdownValue', '.ibexa-dropdown__selection-info, .ids-dropdown__widget'), + new VisibleCSSLocator('dropdownValue', '.ibexa-dropdown__selection-info, .ids-dropdown__widget, .ids-dropdown__selection-info'), new VisibleCSSLocator('radioValue', '.ibexa-dc-extra-actions-applies-to__option'), new VisibleCSSLocator('radioLabel', '.ibexa-label--checkbox-radio'), ]; diff --git a/src/lib/Behat/Component/CreateUrlAliasModal.php b/src/lib/Behat/Component/CreateUrlAliasModal.php index d971af4e56..1b524260ea 100644 --- a/src/lib/Behat/Component/CreateUrlAliasModal.php +++ b/src/lib/Behat/Component/CreateUrlAliasModal.php @@ -75,7 +75,7 @@ protected function specifyLocators(): array new VisibleCSSLocator('title', '#ibexa-modal--custom-url-alias .modal-title'), new VisibleCSSLocator('createButton', '#custom_url_add_add'), new VisibleCSSLocator('pathInput', '#custom_url_add_path'), - new VisibleCSSLocator('languageDropdown', '.ibexa-custom-url-from__item .ibexa-dropdown__selection-info'), + new VisibleCSSLocator('languageDropdown', '.ibexa-custom-url-from__item .ibexa-dropdown__selection-info, ibexa-custom-url-from__item .ids-dropdown__selection-info'), new VisibleCSSLocator('redirectToggle', '.ibexa-custom-url-from__item .ibexa-toggle'), ]; } diff --git a/src/lib/Behat/Component/Fields/Country.php b/src/lib/Behat/Component/Fields/Country.php index cf5e99a26e..ad7d06ad10 100644 --- a/src/lib/Behat/Component/Fields/Country.php +++ b/src/lib/Behat/Component/Fields/Country.php @@ -37,7 +37,7 @@ public function specifyLocators(): array { return [ new VisibleCSSLocator('fieldInput', 'select'), - new VisibleCSSLocator('dropdownSelector', '.ibexa-dropdown__selection-info'), + new VisibleCSSLocator('dropdownSelector', '.ibexa-dropdown__selection-info, .ids-dropdown__selection-info'), ]; } } diff --git a/src/lib/Behat/Component/Fields/Selection.php b/src/lib/Behat/Component/Fields/Selection.php index 31cf32436b..d3a330ff07 100644 --- a/src/lib/Behat/Component/Fields/Selection.php +++ b/src/lib/Behat/Component/Fields/Selection.php @@ -43,9 +43,9 @@ public function getFieldTypeIdentifier(): string public function specifyLocators(): array { return [ - new VisibleCSSLocator('selectBar', '.ibexa-dropdown__selection-info'), - new VisibleCSSLocator('selectOption', '.ibexa-dropdown__item'), - new VisibleCSSLocator('specificOption', '.ibexa-dropdown__item:nth-child(%s)'), + new VisibleCSSLocator('selectBar', '.ibexa-dropdown__selection-info, .ids-dropdown__selection-info'), + new VisibleCSSLocator('selectOption', '.ibexa-dropdown__item, ids-dropdown__item'), + new VisibleCSSLocator('specificOption', '.ibexa-dropdown__item:nth-child(%s), ids-dropdown__item:nth-child(%s)'), ]; } } diff --git a/src/lib/Behat/Component/TrashSearch.php b/src/lib/Behat/Component/TrashSearch.php index 9a5ed8204a..a196e950e3 100644 --- a/src/lib/Behat/Component/TrashSearch.php +++ b/src/lib/Behat/Component/TrashSearch.php @@ -77,7 +77,7 @@ protected function specifyLocators(): array new VisibleCSSLocator('creatorSearchBoxInput', '.ibexa-trash-search-form__item--creator .ibexa-input--text'), new VisibleCSSLocator('mainSearchBoxConfirmButton', '.ibexa-adaptive-filters__static-left .ibexa-input-text-wrapper--type-text .ibexa-input-text-wrapper__action-btn--search'), new VisibleCSSLocator('contentTypeFilterDropdown', 'label[for="trash_search_content_type"] ~ .ibexa-dropdown'), - new VisibleCSSLocator('sectionFilterDropdown', 'label[for="trash_search_section"] ~ .ibexa-dropdown'), + new VisibleCSSLocator('sectionFilterDropdown', 'label[for="trash_search_section"] ~ .ibexa-dropdown, label[for="trash_search_section"] ~ .ids-dropdown'), new VisibleCSSLocator('creatorFilterDropdown', '.ibexa-trash-search-form__user-list li'), ]; } diff --git a/src/lib/Behat/Page/ContentViewPage.php b/src/lib/Behat/Page/ContentViewPage.php index 67e50a00ad..84eff23200 100644 --- a/src/lib/Behat/Page/ContentViewPage.php +++ b/src/lib/Behat/Page/ContentViewPage.php @@ -290,7 +290,7 @@ protected function specifyLocators(): array new VisibleCSSLocator('bookmarkButton', '.ibexa-add-to-bookmarks'), new VisibleCSSLocator('isBookmarked', '.ibexa-add-to-bookmarks--checked'), new VisibleCSSLocator('addTranslationButton', '#ibexa-tab-location-view-translations .ibexa-table-header__actions .ibexa-btn--add-translation, [data-bs-target="#add-translation-modal"]'), - new VisibleCSSLocator('ibexaDropdownPreview', '.ibexa-raw-content-title__language-form .ibexa-dropdown__selection-info'), + new VisibleCSSLocator('ibexaDropdownPreview', '.ibexa-raw-content-title__language-form .ibexa-dropdown__selection-info, .ibexa-raw-content-title__language-form .ids-dropdown__selection-info'), new VisibleCSSLocator('moreTab', '.ibexa-tabs__tab--more'), new VisibleCSSLocator('popupMenuItem', '.ibexa-popup-menu__item .ibexa-popup-menu__item-content'), new VisibleCSSLocator('addUrlAliasButton', '#ibexa-tab-location-view-urls [data-bs-target="#ibexa-modal--custom-url-alias"]'), From 1fe890c9fdf3054e400a350e5a70f6e441afa9e7 Mon Sep 17 00:00:00 2001 From: KamilSznajdrowicz Date: Thu, 11 Jun 2026 15:55:34 +0200 Subject: [PATCH 28/30] Fix --- src/lib/Behat/Component/CreateUrlAliasModal.php | 2 +- src/lib/Behat/Component/Fields/Selection.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/Behat/Component/CreateUrlAliasModal.php b/src/lib/Behat/Component/CreateUrlAliasModal.php index 1b524260ea..515cfad208 100644 --- a/src/lib/Behat/Component/CreateUrlAliasModal.php +++ b/src/lib/Behat/Component/CreateUrlAliasModal.php @@ -75,7 +75,7 @@ protected function specifyLocators(): array new VisibleCSSLocator('title', '#ibexa-modal--custom-url-alias .modal-title'), new VisibleCSSLocator('createButton', '#custom_url_add_add'), new VisibleCSSLocator('pathInput', '#custom_url_add_path'), - new VisibleCSSLocator('languageDropdown', '.ibexa-custom-url-from__item .ibexa-dropdown__selection-info, ibexa-custom-url-from__item .ids-dropdown__selection-info'), + new VisibleCSSLocator('languageDropdown', '.ibexa-custom-url-from__item .ibexa-dropdown__selection-info, .ibexa-custom-url-from__item .ids-dropdown__selection-info'), new VisibleCSSLocator('redirectToggle', '.ibexa-custom-url-from__item .ibexa-toggle'), ]; } diff --git a/src/lib/Behat/Component/Fields/Selection.php b/src/lib/Behat/Component/Fields/Selection.php index d3a330ff07..111ccc52c2 100644 --- a/src/lib/Behat/Component/Fields/Selection.php +++ b/src/lib/Behat/Component/Fields/Selection.php @@ -44,8 +44,8 @@ public function specifyLocators(): array { return [ new VisibleCSSLocator('selectBar', '.ibexa-dropdown__selection-info, .ids-dropdown__selection-info'), - new VisibleCSSLocator('selectOption', '.ibexa-dropdown__item, ids-dropdown__item'), - new VisibleCSSLocator('specificOption', '.ibexa-dropdown__item:nth-child(%s), ids-dropdown__item:nth-child(%s)'), + new VisibleCSSLocator('selectOption', '.ibexa-dropdown__item, .ids-dropdown__item'), + new VisibleCSSLocator('specificOption', '.ibexa-dropdown__item:nth-child(%s), .ids-dropdown__item:nth-child(%s)'), ]; } } From f28349686022e4c22be712952c2ff388d88858c7 Mon Sep 17 00:00:00 2001 From: KamilSznajdrowicz Date: Sun, 14 Jun 2026 17:55:38 +0200 Subject: [PATCH 29/30] Fix expandLastFieldDefinition() method after DS changes --- src/lib/Behat/Page/ContentTypeUpdatePage.php | 39 ++++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/lib/Behat/Page/ContentTypeUpdatePage.php b/src/lib/Behat/Page/ContentTypeUpdatePage.php index ec5e54673d..2549681424 100644 --- a/src/lib/Behat/Page/ContentTypeUpdatePage.php +++ b/src/lib/Behat/Page/ContentTypeUpdatePage.php @@ -33,34 +33,22 @@ public function fillFieldDefinitionFieldWithValue(string $fieldName, string $lab public function expandLastFieldDefinition(): void { - $fieldDefinitionLocator = new VisibleCSSLocator( - 'lastFieldDefinition', - 'div.ibexa-collapse__body-content div.ibexa-collapse--field-definition' - ); - - $this->getHTMLPage()->setTimeout(10)->waitUntil(function () use ($fieldDefinitionLocator): bool { - $fieldDefinition = $this->getHTMLPage()->findAll($fieldDefinitionLocator)->last(); - $fieldDefinition->click(); - $this->getHTMLPage()->setTimeout(3)->waitUntilCondition( - new ElementNotExistsCondition( - $fieldDefinition, - new VisibleCSSLocator('isCollapsed', 'button.collapsed') - ) - ); + $lastFieldDefinition = $this->getHTMLPage()->findAll($this->getLocator('fieldDefinition'))->last(); - return true; - }, 'Error expanding the last Field definition'); + if ($lastFieldDefinition->findAll($this->getLocator('openContainerInField'))->count() === 0) { + $lastFieldDefinition->find($this->getLocator('fieldDefinitionToggle'))->click(); - $lastFieldDefinition = $this->getHTMLPage()->findAll($fieldDefinitionLocator)->last(); - $this - ->getHTMLPage() - ->setTimeout(10) - ->waitUntilCondition( - new ElementTransitionHasEndedCondition( + $lastFieldDefinition->setTimeout(5)->waitUntilCondition( + new ElementNotExistsCondition( $lastFieldDefinition, - new VisibleCSSLocator('transition', 'div') + $this->getLocator('collapsedToggle') ) ); + } + + $this->getHTMLPage()->setTimeout(10)->waitUntilCondition( + new ElementTransitionHasEndedCondition($lastFieldDefinition, $this->getLocator('transition')) + ); } public function specifyLocators(): array @@ -72,11 +60,14 @@ public function specifyLocators(): array new VisibleCSSLocator('contentTypeCategoryList', ' div.ibexa-content-type-edit__add-field-definitions-group > ul > li:nth-child(n):not(.ibexa-popup-menu__item-action--disabled)'), new VisibleCSSLocator('availableFieldLabelList', '.ibexa-available-field-types__list > li:not(.ibexa-available-field-type--hidden)'), new VisibleCSSLocator('workspace', '.ibexa-collapse__body-content'), - new VisibleCSSLocator('fieldDefinitionToggle', '.ibexa-collapse:nth-last-child(2) > div.ibexa-collapse__header > button:last-child:not([data-bs-target="#content_collapse"])'), + new VisibleCSSLocator('fieldDefinitionToggle', '.ibexa-collapse__header > button:last-child'), new VisibleCSSLocator('selectLaunchEditorMode', '.form-check .ibexa-input--radio'), new VisibleCSSLocator('fieldDefinitionOpenContainer', '[data-collapsed="false"] .ibexa-content-type-edit__field-definition-content'), new VisibleCSSLocator('selectBlocksDropdown', '.ibexa-page-select-items__toggler'), new VisibleCSSLocator('fieldDefinitionSearch', '.ibexa-available-field-types__sidebar-filter'), + new VisibleCSSLocator('transition', 'div'), + new VisibleCSSLocator('openContainerInField', '.ibexa-content-type-edit__field-definition-content'), + new VisibleCSSLocator('collapsedToggle', '.ibexa-collapse__header > button[aria-expanded="false"]'), ]); } From e23e6d869623953fbc5c60db2e2fc12117a6b900 Mon Sep 17 00:00:00 2001 From: tischsoic Date: Tue, 16 Jun 2026 09:02:31 +0200 Subject: [PATCH 30/30] refactor: simplify dropdown DS twig conditional merges --- .../component/dropdown/dropdown_ds.html.twig | 84 ++++++++----------- 1 file changed, 36 insertions(+), 48 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig index 82fa542963..e0f0271a88 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/dropdown/dropdown_ds.html.twig @@ -14,10 +14,9 @@ disabled: is_disabled, required: required|default(false), }) %} -{% set normalized_source_attr = source_id is not null - ? normalized_source_attr|merge({ id: source_id }) - : normalized_source_attr -%} +{% if source_id is not null %} + {% set normalized_source_attr = normalized_source_attr|merge({ id: source_id }) %} +{% endif %} {% set translated_placeholder = placeholder is defined and placeholder is not none ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) : null @@ -100,14 +99,12 @@ source, sourceAttributes: normalized_source_attr, } %} - {% set ds_dropdown_props = translated_placeholder is not same as(null) - ? ds_dropdown_props|merge({ placeholder: translated_placeholder }) - : ds_dropdown_props - %} - {% set ds_dropdown_props = is_hidden|default(false) - ? ds_dropdown_props|merge({ hidden: true }) - : ds_dropdown_props - %} + {% if translated_placeholder is not same as(null) %} + {% set ds_dropdown_props = ds_dropdown_props|merge({ placeholder: translated_placeholder }) %} + {% endif %} + {% if is_hidden|default(false) %} + {% set ds_dropdown_props = ds_dropdown_props|merge({ hidden: true }) %} + {% endif %} {% if multiple %} @@ -136,42 +133,33 @@ item_icon_class: item_icon_class|default(''), attr: attr|default({}), } %} - {% set legacy_context = has_selected_item_template_path - ? legacy_context|merge({ selected_item_template_path: selected_item_template_path }) - : legacy_context - %} - {% set legacy_context = has_list_item_template_path - ? legacy_context|merge({ list_item_template_path: list_item_template_path }) - : legacy_context - %} - {% set legacy_context = has_items_class - ? legacy_context|merge({ items_class: items_class }) - : legacy_context - %} - {% set legacy_context = has_items_list_header - ? legacy_context|merge({ items_list_header: items_list_header }) - : legacy_context - %} - {% set legacy_context = item_icon is defined and item_icon is not null - ? legacy_context|merge({ item_icon: item_icon }) - : legacy_context - %} - {% set legacy_context = has_min_search_items - ? legacy_context|merge({ min_search_items: min_search_items }) - : legacy_context - %} - {% set legacy_context = has_min_select_all_toggler_items - ? legacy_context|merge({ min_select_all_toggler_items: min_select_all_toggler_items }) - : legacy_context - %} - {% set legacy_context = has_min_item_width - ? legacy_context|merge({ min_item_width: min_item_width }) - : legacy_context - %} - {% set legacy_context = has_selected_item_label - ? legacy_context|merge({ selected_item_label: selected_item_label }) - : legacy_context - %} + {% if has_selected_item_template_path %} + {% set legacy_context = legacy_context|merge({ selected_item_template_path: selected_item_template_path }) %} + {% endif %} + {% if has_list_item_template_path %} + {% set legacy_context = legacy_context|merge({ list_item_template_path: list_item_template_path }) %} + {% endif %} + {% if has_items_class %} + {% set legacy_context = legacy_context|merge({ items_class: items_class }) %} + {% endif %} + {% if has_items_list_header %} + {% set legacy_context = legacy_context|merge({ items_list_header: items_list_header }) %} + {% endif %} + {% if item_icon is defined and item_icon is not null %} + {% set legacy_context = legacy_context|merge({ item_icon: item_icon }) %} + {% endif %} + {% if has_min_search_items %} + {% set legacy_context = legacy_context|merge({ min_search_items: min_search_items }) %} + {% endif %} + {% if has_min_select_all_toggler_items %} + {% set legacy_context = legacy_context|merge({ min_select_all_toggler_items: min_select_all_toggler_items }) %} + {% endif %} + {% if has_min_item_width %} + {% set legacy_context = legacy_context|merge({ min_item_width: min_item_width }) %} + {% endif %} + {% if has_selected_item_label %} + {% set legacy_context = legacy_context|merge({ selected_item_label: selected_item_label }) %} + {% endif %} {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with legacy_context only %} {% endif %}