diff --git a/.changeset/curly-phones-burn.md b/.changeset/curly-phones-burn.md new file mode 100644 index 0000000000..8e273bce36 --- /dev/null +++ b/.changeset/curly-phones-burn.md @@ -0,0 +1,5 @@ +--- +'@primer/view-components': patch +--- + +[SelectPanel] Fix tab index issue in multi-select mode diff --git a/app/components/primer/alpha/select_panel_element.ts b/app/components/primer/alpha/select_panel_element.ts index f450a1e86c..af1396bf70 100644 --- a/app/components/primer/alpha/select_panel_element.ts +++ b/app/components/primer/alpha/select_panel_element.ts @@ -314,11 +314,7 @@ export class SelectPanelElement extends HTMLElement { const itemContent = this.#getItemContent(item) if (!itemContent) continue - if (!this.isItemHidden(item) && !setZeroTabIndex) { - setZeroTabIndex = true - } else { - itemContent.setAttribute('tabindex', '-1') - } + itemContent.setAttribute('tabindex', '-1') //
  • elements should not themselves be tabbable item.removeAttribute('tabindex') @@ -742,6 +738,8 @@ export class SelectPanelElement extends HTMLElement { return true } + if (!this.bannerErrorElement) return false + return !this.bannerErrorElement.hasAttribute('hidden') } diff --git a/test/system/alpha/select_panel_test.rb b/test/system/alpha/select_panel_test.rb index 9ce82caffc..1eb60d4644 100644 --- a/test/system/alpha/select_panel_test.rb +++ b/test/system/alpha/select_panel_test.rb @@ -82,6 +82,21 @@ def wait_for_dialog_ready end def filter_results(query:) + input = find("input") + + # If the query is an empty string or nil, using fill_in does not + # trigger the right type of input event, which in turn prevents + # the remote-input element from firing its remote-input-success + # event. Instead we have to focus on the input field, select all + # the text, and press backspace. Doing so fires the right type of + # event and clears the input. + if query.blank? + old_active_element = active_element + input.evaluate_script("this.focus()") + keyboard.type([:control, "a"], :backspace) + old_active_element.evaluate_script("this.focus()") + end + find("input").fill_in(with: query) end @@ -1052,6 +1067,21 @@ def test_arrowing_skips_filtered_items end end + def test_can_tab_to_first_item_after_filtering + visit_preview(:local_fetch) + + click_on_invoker_button + + filter_results(query: "2") + assert_selector "select-panel ul li", count: 1 + + filter_results(query: "") + keyboard.type(:tab) + assert_equal active_element.text, "Item 1" + end + + ########## FORM TESTS ############ + def test_single_select_form visit_preview(:single_select_form, route_format: :json)