Skip to content

Commit

Permalink
TreeView: Fix expanding/collapsing item when Space is pressed (#4548
Browse files Browse the repository at this point in the history
)

* Account for the {Space} key event

* Create quiet-lamps-kiss.md

* Update quiet-lamps-kiss.md

---------

Co-authored-by: Ian Sanders <iansan5653@github.com>
Co-authored-by: Siddharth Kshetrapal <siddharthkp@github.com>
  • Loading branch information
3 people committed May 8, 2024
1 parent e39fcf8 commit 95cd867
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-lamps-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": patch
---

TreeView: Fix toggling subtree via Space key (in addition to Enter key)
96 changes: 96 additions & 0 deletions packages/react/src/TreeView/TreeView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,102 @@ describe('Keyboard interactions', () => {
})
})

describe('Space', () => {
it('calls onSelect function if provided and checks if the item has been selected', () => {
const onSelect = jest.fn()
const {getByRole} = renderWithTheme(
<TreeView aria-label="Test tree">
<TreeView.Item id="parent-1" onSelect={onSelect}>
Parent 1
<TreeView.SubTree>
<TreeView.Item id="child-1" onSelect={onSelect}>
Child 1
</TreeView.Item>
</TreeView.SubTree>
</TreeView.Item>
<TreeView.Item id="parent-2" onSelect={onSelect} expanded>
Parent 2
<TreeView.SubTree>
<TreeView.Item id="child-2" onSelect={onSelect}>
Child2
</TreeView.Item>
</TreeView.SubTree>
</TreeView.Item>
<TreeView.Item id="parent-3" onSelect={onSelect}>
Parent 3
<TreeView.SubTree>
<TreeView.Item id="child-3" onSelect={onSelect}>
Child 3
</TreeView.Item>
</TreeView.SubTree>
</TreeView.Item>
</TreeView>,
)
const itemChild = getByRole('treeitem', {name: 'Child2'})

act(() => {
// Focus first item
itemChild.focus()
})

// Press Enter
fireEvent.keyDown(document.activeElement || document.body, {key: ' '})

// onSelect should have been called
expect(onSelect).toHaveBeenCalledTimes(1)

onSelect.mockClear()

// Press middle click
fireEvent.click(document.activeElement?.firstChild || document.body, {button: 1})

// onSelect should have been called
expect(onSelect).toHaveBeenCalledTimes(1)
})

it('toggles expanded state if no onSelect function is provided', () => {
const {getByRole, queryByRole} = renderWithTheme(
<TreeView aria-label="Test tree">
<TreeView.Item id="parent">
Parent
<TreeView.SubTree>
<TreeView.Item id="child-1">Child 1</TreeView.Item>
<TreeView.Item id="child-2">Child 2</TreeView.Item>
</TreeView.SubTree>
</TreeView.Item>
</TreeView>,
)

const parent = getByRole('treeitem', {name: 'Parent'})

act(() => {
// Focus first item
parent.focus()
})

// aria-expanded should be false
expect(parent).toHaveAttribute('aria-expanded', 'false')

// Press Enter
fireEvent.keyDown(document.activeElement || document.body, {key: 'Enter'})

// aria-expanded should now be true
expect(parent).toHaveAttribute('aria-expanded', 'true')

// Subtree should be visible
expect(queryByRole('group')).toBeVisible()

// Press Enter
fireEvent.keyDown(document.activeElement || document.body, {key: 'Enter'})

// aria-expanded should now be false
expect(parent).toHaveAttribute('aria-expanded', 'false')

// Subtree should no longer be visible
expect(queryByRole('group')).not.toBeInTheDocument()
})
})

describe('Typeahead', () => {
it('moves focus to the next item that matches the typed character', () => {
const {getByRole} = renderWithTheme(
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/TreeView/TreeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ const Item = React.forwardRef<HTMLElement, TreeViewItemProps>(
(event: React.KeyboardEvent<HTMLElement>) => {
switch (event.key) {
case 'Enter':
case 'Space':
case ' ':
if (onSelect) {
onSelect(event)
} else {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/TreeView/useTypeahead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function useTypeahead({containerRef, onFocusChange}: TypeaheadOptions) {

function onKeyDown(event: KeyboardEvent) {
// Ignore key presses that don't produce a character value
if (!event.key || event.key.length > 1) return
if (!event.key || event.key.length > 1 || event.key === ' ') return

// Ignore key presses that occur with a modifier
if (event.ctrlKey || event.altKey || event.metaKey) return
Expand Down

0 comments on commit 95cd867

Please sign in to comment.