Skip to content

Commit 7efbd32

Browse files
authored
Make AvatarStack accessible via keyboard navigation (#3849)
1 parent 4a47977 commit 7efbd32

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

.changeset/tough-students-guess.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/view-components": patch
3+
---
4+
5+
Make AvatarStack accessible via keyboard navigation

app/components/primer/beta/avatar.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ module Beta
1919
class Avatar < Primer::Component
2020
status :beta
2121

22+
def link?
23+
@href.present?
24+
end
25+
2226
DEFAULT_SIZE = 20
2327
SMALL_THRESHOLD = 24
2428

app/components/primer/beta/avatar_stack.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ def before_render
7979
"AvatarStack--two" => avatars.size == 2,
8080
"AvatarStack--three-plus" => avatars.size > 2
8181
)
82+
83+
# Make non-linked stacks keyboard-focusable so :focus-within triggers expansion (avoid extra focus stop when avatars are links).
84+
unless @tooltipped || @disable_expand
85+
has_linked_avatars = avatars.any?(&:link?)
86+
@body_arguments[:tabindex] ||= 0 unless has_linked_avatars
87+
end
8288
end
8389

8490
def render?

test/components/beta/avatar_stack_test.rb

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def test_renders_default_body
5050
end
5151

5252
assert_selector(".AvatarStack") do
53-
refute_selector(".toltipped")
53+
refute_selector(".tooltipped")
5454
assert_selector(".AvatarStack-body") do
5555
assert_selector("img.avatar", count: 1)
5656
end
@@ -75,7 +75,7 @@ def test_renders_right_aligned
7575
end
7676

7777
assert_selector(".AvatarStack.AvatarStack--right") do
78-
refute_selector(".toltipped")
78+
refute_selector(".tooltipped")
7979
assert_selector(".AvatarStack-body") do
8080
assert_selector("img.avatar", count: 1)
8181
end
@@ -138,4 +138,39 @@ def test_renders_avatars_with_individual_tooltips
138138
end
139139
end
140140
end
141+
142+
def test_adds_tabindex_when_expandable_and_avatars_are_not_links
143+
render_inline(Primer::Beta::AvatarStack.new) do |component|
144+
component.with_avatar(src: "Foo", alt: "Bar")
145+
component.with_avatar(src: "Foo", alt: "Bar")
146+
end
147+
148+
assert_selector(".AvatarStack-body[tabindex='0']")
149+
end
150+
151+
def test_does_not_add_tabindex_when_disable_expand_is_true
152+
render_inline(Primer::Beta::AvatarStack.new(disable_expand: true)) do |component|
153+
component.with_avatar(src: "Foo", alt: "Bar")
154+
component.with_avatar(src: "Foo", alt: "Bar")
155+
end
156+
157+
refute_selector(".AvatarStack-body[tabindex]")
158+
end
159+
160+
def test_does_not_add_tabindex_when_any_avatar_is_a_link
161+
render_inline(Primer::Beta::AvatarStack.new) do |component|
162+
component.with_avatar(src: "Foo", alt: "Bar", href: "https://github.com/user1")
163+
component.with_avatar(src: "Foo", alt: "Bar")
164+
end
165+
166+
refute_selector(".AvatarStack-body[tabindex]")
167+
end
168+
169+
def test_adds_tabindex_when_tooltipped
170+
render_inline(Primer::Beta::AvatarStack.new(tooltipped: true, body_arguments: { label: "Tooltip" })) do |component|
171+
component.with_avatar(src: "Foo", alt: "Bar")
172+
end
173+
174+
assert_selector(".AvatarStack-body[tabindex='0']")
175+
end
141176
end

0 commit comments

Comments
 (0)