From 7ea7c65e9c90bdc09b4934afdd92274e35d7d861 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Wed, 4 Mar 2026 12:47:14 -0800 Subject: [PATCH 1/5] fix multiselect dropdown with components as labels --- .../src/fragments/Dropdown.tsx | 2 +- .../tests/integration/dropdown/test_a11y.py | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/components/dash-core-components/src/fragments/Dropdown.tsx b/components/dash-core-components/src/fragments/Dropdown.tsx index 8338d03689..8fd163bfe9 100644 --- a/components/dash-core-components/src/fragments/Dropdown.tsx +++ b/components/dash-core-components/src/fragments/Dropdown.tsx @@ -233,7 +233,7 @@ const Dropdown = (props: DropdownProps) => { setDisplayOptions(sortedOptions); } - }, [filteredOptions, isOpen]); + }, [filteredOptions, isOpen, sanitizedValues]); // Focus first selected item or search input when dropdown opens useEffect(() => { diff --git a/components/dash-core-components/tests/integration/dropdown/test_a11y.py b/components/dash-core-components/tests/integration/dropdown/test_a11y.py index d547390ca4..a581558d11 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_a11y.py +++ b/components/dash-core-components/tests/integration/dropdown/test_a11y.py @@ -1,7 +1,7 @@ import pytest from dash import Dash, Input, Output from dash.dcc import Dropdown -from dash.html import Div, Label, P +from dash.html import Div, Label, P, Span from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains @@ -434,3 +434,40 @@ def is_visible(el): ) return all([is_visible(el) for el in elements]) + + +def test_a11y009_dropdown_component_labels_render_correctly(dash_duo): + app = Dash(__name__) + app.layout = Div( + [ + Dropdown( + options=[ + {"label": Span("red"), "value": "red"}, + {"label": Span("yellow"), "value": "yellow"}, + {"label": Span("blue"), "value": "blue"}, + ], + value=["red", "yellow", "blue"], + id="components-label-dropdown", + multi=True, + ), + ] + ) + + dash_duo.start_server(app) + + dash_duo.find_element("#components-label-dropdown").click() + dash_duo.wait_for_element(".dash-dropdown-options") + + # Click on the "yellow" option + yellow_option = dash_duo.find_element( + '.dash-dropdown-option:has(input[value="yellow"])' + ) + yellow_option.click() + + # After interaction, verify the options render correctly + option_elements = dash_duo.find_elements(".dash-dropdown-option") + rendered_labels = [el.text.strip() for el in option_elements] + + assert rendered_labels == ["red", "blue", "yellow"] + + assert dash_duo.get_logs() == [] From ff8961fd20b80bb8b7694b39eef5c503659aba45 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Wed, 4 Mar 2026 13:50:38 -0800 Subject: [PATCH 2/5] fixed test --- .../integration/dropdown/test_clearable_false.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py b/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py index 7d2e3bbcc1..7681de98fe 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py +++ b/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py @@ -190,8 +190,17 @@ def update_value(val): # Attempt to deselect all items. Everything should deselect until we get to # the last item which cannot be cleared. - selected = dash_duo.find_elements(".dash-dropdown-options input[checked]") - [el.click() for el in selected] + # Click MTL option container + mtl_option = dash_duo.find_element( + '.dash-dropdown-option:has(input[value="MTL"])' + ) + mtl_option.click() + + # Click SF option container + sf_option = dash_duo.find_element( + '.dash-dropdown-option:has(input[value="SF"])' + ) + sf_option.click() assert dash_duo.find_element("#dropdown-value").text == "SF" From 98f206463b4030c9a89611e6349889f9c9859a95 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Wed, 11 Mar 2026 16:29:47 -0700 Subject: [PATCH 3/5] update after review --- components/dash-core-components/src/fragments/Dropdown.tsx | 2 +- components/dash-core-components/src/utils/optionRendering.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/dash-core-components/src/fragments/Dropdown.tsx b/components/dash-core-components/src/fragments/Dropdown.tsx index 8fd163bfe9..8338d03689 100644 --- a/components/dash-core-components/src/fragments/Dropdown.tsx +++ b/components/dash-core-components/src/fragments/Dropdown.tsx @@ -233,7 +233,7 @@ const Dropdown = (props: DropdownProps) => { setDisplayOptions(sortedOptions); } - }, [filteredOptions, isOpen, sanitizedValues]); + }, [filteredOptions, isOpen]); // Focus first selected item or search input when dropdown opens useEffect(() => { diff --git a/components/dash-core-components/src/utils/optionRendering.tsx b/components/dash-core-components/src/utils/optionRendering.tsx index 014f42e6b8..70c1d2c0d1 100644 --- a/components/dash-core-components/src/utils/optionRendering.tsx +++ b/components/dash-core-components/src/utils/optionRendering.tsx @@ -37,7 +37,7 @@ export const OptionLabel: React.FC = ({ ))} From 1edb877ee2359bef82d9859e82fb0b368b797255 Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Wed, 11 Mar 2026 16:30:10 -0700 Subject: [PATCH 4/5] update after review --- .../tests/integration/dropdown/test_a11y.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/tests/integration/dropdown/test_a11y.py b/components/dash-core-components/tests/integration/dropdown/test_a11y.py index a581558d11..39dfce435d 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_a11y.py +++ b/components/dash-core-components/tests/integration/dropdown/test_a11y.py @@ -468,6 +468,6 @@ def test_a11y009_dropdown_component_labels_render_correctly(dash_duo): option_elements = dash_duo.find_elements(".dash-dropdown-option") rendered_labels = [el.text.strip() for el in option_elements] - assert rendered_labels == ["red", "blue", "yellow"] + assert rendered_labels == ["red", "yellow", "blue"] assert dash_duo.get_logs() == [] From c634cf574544605a929e7e0cd30aa464ef95e7df Mon Sep 17 00:00:00 2001 From: AnnMarueW Date: Wed, 11 Mar 2026 16:47:43 -0700 Subject: [PATCH 5/5] lint --- .../tests/integration/dropdown/test_clearable_false.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py b/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py index 7681de98fe..219b98acb1 100644 --- a/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py +++ b/components/dash-core-components/tests/integration/dropdown/test_clearable_false.py @@ -191,15 +191,11 @@ def update_value(val): # Attempt to deselect all items. Everything should deselect until we get to # the last item which cannot be cleared. # Click MTL option container - mtl_option = dash_duo.find_element( - '.dash-dropdown-option:has(input[value="MTL"])' - ) + mtl_option = dash_duo.find_element('.dash-dropdown-option:has(input[value="MTL"])') mtl_option.click() # Click SF option container - sf_option = dash_duo.find_element( - '.dash-dropdown-option:has(input[value="SF"])' - ) + sf_option = dash_duo.find_element('.dash-dropdown-option:has(input[value="SF"])') sf_option.click() assert dash_duo.find_element("#dropdown-value").text == "SF"