Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/seven-papayas-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/view-components': patch
---

Fixed SelectPanel multiselect accessibility: Use `aria-selected` instead of `aria-checked` for listbox option items.
2 changes: 1 addition & 1 deletion app/components/primer/alpha/select_panel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def initialize(**system_arguments)
super(
p: 2,
role: "listbox",
aria_selection_variant: select_variant == :single ? :selected : :checked,
aria_selection_variant: :selected,
select_variant: select_variant == :multiple ? :multiple_checkbox : :single,
**system_arguments
)
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/select_panel_element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class SelectPanelElement extends HTMLElement {
}

get ariaSelectionType(): string {
return this.selectVariant === 'multiple' ? 'aria-checked' : 'aria-selected'
return 'aria-selected'
}

set selectVariant(variant: SelectVariant) {
Expand Down
69 changes: 28 additions & 41 deletions test/system/alpha/select_panel_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,18 @@ def test_remembers_selections_on_filter
end

# Phaser should already be selected
assert_selector "[aria-checked=true]", text: "Phaser"
assert_selector "[aria-selected=true]", text: "Phaser"

click_on "Photon torpedo"

assert_selector "[aria-checked=true]", text: "Phaser"
assert_selector "[aria-checked=true]", text: "Photon torpedo"
assert_selector "[aria-selected=true]", text: "Phaser"
assert_selector "[aria-selected=true]", text: "Photon torpedo"

wait_for_items_to_load do
filter_results(query: "ph")
end

assert_selector "[aria-checked=true]", count: 2
assert_selector "[aria-selected=true]", count: 2
end

def test_pressing_down_arrow_in_filter_input_focuses_first_item
Expand Down Expand Up @@ -270,16 +270,15 @@ def test_pressing_enter_in_filter_input_checks_first_item
click_on_invoker_button

# nothing is checked initially
refute_selector "[aria-checked=true]"
refute_selector "[aria-selected=true]"
refute_selector "[aria-selected=true]"

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate assertion: there are two consecutive refute_selector "[aria-selected=true]" lines. This is redundant and can be reduced to a single assertion (or replaced with a more specific check, e.g., count-based, if you intended to assert something else).

Suggested change
refute_selector "[aria-selected=true]"

Copilot uses AI. Check for mistakes.

assert_equal active_element.tag_name, "input"

keyboard.type(:enter)

# pressing enter in the filter input does not close the panel
assert_selector "[aria-checked=true]", text: "Item 1"
refute_selector "[aria-selected]"
assert_selector "[aria-selected=true]", text: "Item 1"
end

def test_pressing_enter_in_filter_input_navigates_if_first_item_is_link
Expand Down Expand Up @@ -316,7 +315,6 @@ def test_single_select_item_checked

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=true]", text: "Item 2", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden
end

def test_single_select_remote_fetch_item_checked
Expand All @@ -327,7 +325,6 @@ def test_single_select_remote_fetch_item_checked

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=true]", text: "Photon torpedo", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden
end

def test_single_select_item_checked_via_keyboard_enter
Expand Down Expand Up @@ -359,7 +356,6 @@ def test_single_select_item_checked_via_keyboard_enter
keyboard.type(:tab, :down, :enter)

assert_selector "[aria-selected=true]", text: "Item 2", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden
end

def test_single_select_item_checked_via_keyboard_space
Expand Down Expand Up @@ -391,7 +387,6 @@ def test_single_select_item_checked_via_keyboard_space
keyboard.type(:tab, :down, :space)

assert_selector "[aria-selected=true]", text: "Item 2", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden
end

def test_single_select_item_unchecks_previously_checked_item
Expand All @@ -402,14 +397,12 @@ def test_single_select_item_unchecks_previously_checked_item

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=true]", text: "Item 3", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden

click_on_invoker_button
click_on_second_item

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=true]", text: "Item 2", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden
end

def test_single_select_item_unchecks_previously_checked_item_after_filtering
Expand All @@ -419,7 +412,6 @@ def test_single_select_item_unchecks_previously_checked_item_after_filtering

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=true]", text: "Phaser"
refute_selector "[aria-checked]"

wait_for_items_to_load do
filter_results(query: "ph")
Expand All @@ -431,7 +423,6 @@ def test_single_select_item_unchecks_previously_checked_item_after_filtering
# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=false]", text: "Phaser"
assert_selector "[aria-selected=true]", text: "Photon torpedo"
refute_selector "[aria-checked]"
end

def test_single_selected_item_cannot_be_unchecked
Expand All @@ -445,7 +436,6 @@ def test_single_selected_item_cannot_be_unchecked

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-selected=true]", text: "Item 2", visible: :hidden
refute_selector "[aria-checked]", visible: :hidden
end

def test_single_select_clears_input_on_selection
Expand Down Expand Up @@ -614,9 +604,8 @@ def test_multi_select_items_checked
click_on_third_item

# clicking item closes panel, so checked item is hidden
assert_selector "[aria-checked=true]", text: "Item 2"
assert_selector "[aria-checked=true]", text: "Item 3"
refute_selector "[aria-selected]", visible: :hidden
assert_selector "[aria-selected=true]", text: "Item 2"
assert_selector "[aria-selected=true]", text: "Item 3"
end

def test_multi_select_items_checked_via_keyboard_enter
Expand All @@ -633,17 +622,16 @@ def test_multi_select_items_checked_via_keyboard_enter
# select first item
keyboard.type(:tab, :enter)

assert_selector "[aria-checked=true]", count: 1
assert_selector "[aria-checked=true]", text: "Item 1"
assert_selector "[aria-selected=true]", count: 1
assert_selector "[aria-selected=true]", text: "Item 1"

# select second item
keyboard.type(:down, :enter)

assert_selector "[aria-checked=true]", count: 2
assert_selector "[aria-checked=true]", text: "Item 1"
assert_selector "[aria-checked=true]", text: "Item 2"
assert_selector "[aria-selected=true]", count: 2
assert_selector "[aria-selected=true]", text: "Item 1"
assert_selector "[aria-selected=true]", text: "Item 2"

refute_selector "[aria-selected]", visible: :hidden
end

def test_multi_select_items_checked_via_keyboard_space
Expand All @@ -660,17 +648,16 @@ def test_multi_select_items_checked_via_keyboard_space
# select first item
keyboard.type(:tab, :space)

assert_selector "[aria-checked=true]", count: 1
assert_selector "[aria-checked=true]", text: "Item 1"
assert_selector "[aria-selected=true]", count: 1
assert_selector "[aria-selected=true]", text: "Item 1"

# select second item
keyboard.type(:down, :space)

assert_selector "[aria-checked=true]", count: 2
assert_selector "[aria-checked=true]", text: "Item 1"
assert_selector "[aria-checked=true]", text: "Item 2"
assert_selector "[aria-selected=true]", count: 2
assert_selector "[aria-selected=true]", text: "Item 1"
assert_selector "[aria-selected=true]", text: "Item 2"

refute_selector "[aria-selected]", visible: :hidden
end

def test_multi_select_items_can_be_unchecked
Expand All @@ -680,13 +667,13 @@ def test_multi_select_items_can_be_unchecked
click_on_second_item
click_on_third_item

assert_selector "[aria-checked=true]", text: "Item 2"
assert_selector "[aria-checked=true]", text: "Item 3"
assert_selector "[aria-selected=true]", text: "Item 2"
assert_selector "[aria-selected=true]", text: "Item 3"

click_on_second_item
click_on_third_item

refute_selector "[aria-checked=true]"
refute_selector "[aria-selected=true]"
end

def test_multi_select_disabled_item_cannot_be_checked
Expand All @@ -696,7 +683,7 @@ def test_multi_select_disabled_item_cannot_be_checked

click_on_item_by_id("disabled")

refute_selector "[aria-checked=true]"
refute_selector "[aria-selected=true]"
end

def test_multi_select_does_not_allow_server_to_check_items_on_filter_if_selections_already_made
Expand All @@ -708,7 +695,7 @@ def test_multi_select_does_not_allow_server_to_check_items_on_filter_if_selectio
end

# Phaser should already be selected
assert_selector "[aria-checked=true]", text: "Phaser"
assert_selector "[aria-selected=true]", text: "Phaser"

# check torpedo, uncheck phaser
click_on "Photon torpedo"
Expand All @@ -720,8 +707,8 @@ def test_multi_select_does_not_allow_server_to_check_items_on_filter_if_selectio

# server will render phaser checked, but since the user has already made selections,
# the server-rendered selections should be ignored
refute_selector "[aria-checked=true]", text: "Phaser"
assert_selector "[aria-checked=true]", text: "Photon torpedo"
refute_selector "[aria-selected=true]", text: "Phaser"
assert_selector "[aria-selected=true]", text: "Photon torpedo"
end

def test_multi_select_allows_server_to_check_multiple_items
Expand All @@ -732,8 +719,8 @@ def test_multi_select_allows_server_to_check_multiple_items
click_on_invoker_button
end

assert_selector "[aria-checked=true]", text: "Phaser"
assert_selector "[aria-checked=true]", text: "Photon torpedo"
assert_selector "[aria-selected=true]", text: "Phaser"
assert_selector "[aria-selected=true]", text: "Photon torpedo"
end

def test_banner_scheme_is_passed_to_banner_component
Expand Down Expand Up @@ -804,7 +791,7 @@ def test_uncheck_item_via_js_api
click_on_invoker_button
click_on_item_by_id("item1")

assert_selector "li[data-item-id=item1] [aria-checked=true]"
assert_selector "li[data-item-id=item1] [aria-selected=true]"

evaluate_multiline_script(<<~JS)
const panel = document.querySelector('select-panel')
Expand Down
Loading