diff --git a/.changeset/afraid-monkeys-unite.md b/.changeset/afraid-monkeys-unite.md new file mode 100644 index 0000000000..3f3b8dfc5d --- /dev/null +++ b/.changeset/afraid-monkeys-unite.md @@ -0,0 +1,5 @@ +--- +'@openproject/primer-view-components': minor +--- + +Support dynamic labels for SelectPanel multiple select variant diff --git a/.playwright/screenshots/snapshots.test.ts-snapshots/primer/open_project/filterable_tree_view/custom_segmented_control/dark_high_contrast.png b/.playwright/screenshots/snapshots.test.ts-snapshots/primer/open_project/filterable_tree_view/custom_segmented_control/dark_high_contrast.png index 3ad3aa47b8..6cd8569021 100644 Binary files a/.playwright/screenshots/snapshots.test.ts-snapshots/primer/open_project/filterable_tree_view/custom_segmented_control/dark_high_contrast.png and b/.playwright/screenshots/snapshots.test.ts-snapshots/primer/open_project/filterable_tree_view/custom_segmented_control/dark_high_contrast.png differ diff --git a/app/components/primer/alpha/select_panel_element.ts b/app/components/primer/alpha/select_panel_element.ts index ae7d8264fa..556d834708 100644 --- a/app/components/primer/alpha/select_panel_element.ts +++ b/app/components/primer/alpha/select_panel_element.ts @@ -916,6 +916,8 @@ export class SelectPanelElement extends HTMLElement { } else { this.#removeSelectedItem(item) } + + this.#setDynamicLabel() } this.#updateInput() @@ -952,8 +954,15 @@ export class SelectPanelElement extends HTMLElement { const invokerLabel = this.invokerLabel if (!invokerLabel) return this.#originalLabel ||= invokerLabel.textContent || '' - const itemLabel = - this.querySelector(`[${this.ariaSelectionType}=true] .ActionListItem-label`)?.textContent || this.#originalLabel + let itemLabel: string | undefined + if (this.selectVariant === 'single') { + itemLabel = this.querySelector(`[${this.ariaSelectionType}=true] .ActionListItem-label`)?.textContent + } else if (this.selectVariant === 'multiple') { + itemLabel = Array.from(this.querySelectorAll(`[${this.ariaSelectionType}=true] .ActionListItem-label`)) + .map(label => label.textContent?.trim() ?? '') + .join(', ') + } + itemLabel ||= this.#originalLabel if (itemLabel) { const prefixSpan = document.createElement('span') prefixSpan.classList.add('color-fg-muted') diff --git a/previews/primer/alpha/select_panel_preview.rb b/previews/primer/alpha/select_panel_preview.rb index 3ed0a539ed..d14b059018 100644 --- a/previews/primer/alpha/select_panel_preview.rb +++ b/previews/primer/alpha/select_panel_preview.rb @@ -144,15 +144,25 @@ def multiselect(open_on_load: false) # @label With dynamic label # # @param open_on_load toggle - def with_dynamic_label(open_on_load: false) - render_with_template(locals: { open_on_load: open_on_load }) + # @param select_variant [Symbol] select [single, multiple] + def with_dynamic_label(open_on_load: false, select_variant: :single) + render_with_template(locals: { + open_on_load: open_on_load, + # .to_sym workaround for https://github.com/lookbook-hq/lookbook/issues/640 + select_variant: select_variant.to_sym + }) end # @label With dynamic label and aria prefix # # @param open_on_load toggle - def with_dynamic_label_and_aria_prefix(open_on_load: false) - render_with_template(locals: { open_on_load: open_on_load }) + # @param select_variant [Symbol] select [single, multiple] + def with_dynamic_label_and_aria_prefix(open_on_load: false, select_variant: :single) + render_with_template(locals: { + open_on_load: open_on_load, + # .to_sym workaround for https://github.com/lookbook-hq/lookbook/issues/640 + select_variant: select_variant.to_sym + }) end # @!endgroup diff --git a/previews/primer/alpha/select_panel_preview/with_dynamic_label.html.erb b/previews/primer/alpha/select_panel_preview/with_dynamic_label.html.erb index d8010aa017..269b5bd804 100644 --- a/previews/primer/alpha/select_panel_preview/with_dynamic_label.html.erb +++ b/previews/primer/alpha/select_panel_preview/with_dynamic_label.html.erb @@ -4,7 +4,7 @@ data: { interaction_subject: subject_id }, id: "with_avatar_items", title: "Select users", - select_variant: :single, + select_variant: select_variant, fetch_strategy: :local, dynamic_label: true, dynamic_label_prefix: "Item", diff --git a/previews/primer/alpha/select_panel_preview/with_dynamic_label_and_aria_prefix.html.erb b/previews/primer/alpha/select_panel_preview/with_dynamic_label_and_aria_prefix.html.erb index 792f4bf7f3..bbea0676bf 100644 --- a/previews/primer/alpha/select_panel_preview/with_dynamic_label_and_aria_prefix.html.erb +++ b/previews/primer/alpha/select_panel_preview/with_dynamic_label_and_aria_prefix.html.erb @@ -4,7 +4,7 @@ data: { interaction_subject: subject_id }, id: "with_avatar_items", title: "Select users", - select_variant: :single, + select_variant: select_variant, fetch_strategy: :local, dynamic_label: true, dynamic_label_prefix: "Item", diff --git a/test/system/alpha/select_panel_test.rb b/test/system/alpha/select_panel_test.rb index c48cee706a..a2b9b2b1d4 100644 --- a/test/system/alpha/select_panel_test.rb +++ b/test/system/alpha/select_panel_test.rb @@ -737,6 +737,56 @@ def test_banner_scheme_is_passed_to_banner_component assert_selector "[data-target='select-panel.bannerErrorElement'] .Banner--warning", text: "Sorry, something went wrong" end + def test_dynamic_label_for_single_select_variant + visit_preview(:with_dynamic_label, select_variant: :single) + + click_on_invoker_button + + assert_selector "select-panel button[aria-controls]", exact_text: "Item: Choose item" + + click_on_second_item + + assert_selector "select-panel button[aria-controls]", exact_text: "Item: Item 2" + end + + def test_dynamic_label_for_multiple_select_variant + visit_preview(:with_dynamic_label, select_variant: :multiple) + + click_on_invoker_button + + assert_selector "select-panel button[aria-controls]", exact_text: "Item: Choose item" + + click_on_second_item + click_on_third_item + + assert_selector "select-panel button[aria-controls]", exact_text: "Item: Item 2, Item 3" + end + + def test_dynamic_label_and_aria_prefix_for_single_select_variant + visit_preview(:with_dynamic_label_and_aria_prefix, select_variant: :single) + + click_on_invoker_button + + assert_selector "select-panel button[aria-controls][aria-label='Your item: Choose item']" + + click_on_second_item + + assert_selector "select-panel button[aria-controls][aria-label='Your item: Item 2']" + end + + def test_dynamic_label_and_aria_prefix_for_multiple_select_variant + visit_preview(:with_dynamic_label_and_aria_prefix, select_variant: :multiple) + + click_on_invoker_button + + assert_selector "select-panel button[aria-controls][aria-label='Your item: Choose item']" + + click_on_second_item + click_on_third_item + + assert_selector "select-panel button[aria-controls][aria-label='Your item: Item 2, Item 3']" + end + ########## JAVASCRIPT API TESTS ############ def test_disable_item_via_js_api