Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
18 changes: 17 additions & 1 deletion src/sidebar/components/ThreadCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ function ThreadCard({ frameSync, thread }: ThreadCardProps) {
)}
data-testid="thread-card"
elementRef={cardRef}
tabIndex={-1}
tabIndex={0}
role="article"
aria-label="Press Enter to scroll annotation into view"
onClick={e => {
// Prevent click events intended for another action from
// triggering a page scroll.
Expand All @@ -91,6 +93,20 @@ function ThreadCard({ frameSync, thread }: ThreadCardProps) {
}}
onMouseEnter={() => setThreadHovered(thread.annotation ?? null)}
onMouseLeave={() => setThreadHovered(null)}
onKeyDown={e => {
// Simulate default button behavior, where `Enter` and `Space` trigger
// click action
if (
// Trigger event only if the target is the card itself, so that we do
// not scroll to the annotation while editing it, or if the key is
// pressed to interact with a child button or link.
e.target === cardRef.current &&
['Enter', ' '].includes(e.key) &&
thread.annotation
) {
scrollToAnnotation(thread.annotation);
}
}}
key={thread.id}
>
<CardContent>{threadContent}</CardContent>
Expand Down
28 changes: 28 additions & 0 deletions src/sidebar/components/test/ThreadCard-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,34 @@ describe('ThreadCard', () => {
});
});

describe('key down', () => {
[
{ key: 'Enter', shouldScroll: true },
{ key: ' ', shouldScroll: true },
{ key: 'ArrowUp', shouldScroll: false },
{ key: 'Escape', shouldScroll: false },
].forEach(({ key, shouldScroll }) => {
it('scrolls to the annotation when Enter or Space are pressed on the `ThreadCard`', () => {
const wrapper = createComponent();

wrapper.find(threadCardSelector).simulate('keydown', { key });

assert.equal(fakeFrameSync.scrollToAnnotation.called, shouldScroll);
});
});

it('does not scroll to annotation when key is pressed in `ThreadCard` targeting other element', () => {
const wrapper = createComponent();

wrapper
.find(threadCardSelector)
.props()
.onKeyDown({ key: 'Enter', target: document.createElement('a') });

assert.notCalled(fakeFrameSync.scrollToAnnotation);
});
});

it(
'should pass a11y checks',
checkAccessibility({
Expand Down