Skip to content

Commit

Permalink
feat(Table): support table scrolling through keyboard arrow keys (#463)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonguo authored Oct 17, 2023
1 parent 0e0c8dc commit bf451a8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
5 changes: 4 additions & 1 deletion src/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,8 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
onScrollBody,
onScrollTop,
onScrollLeft,
onScrollTo
onScrollTo,
onScrollByKeydown
} = useScrollListener({
rtl,
data: dataProp,
Expand Down Expand Up @@ -1110,6 +1111,8 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
className={classes}
style={styles}
ref={tableRef}
tabIndex={-1}
onKeyDown={onScrollByKeydown}
>
{showHeader && renderTableHeader(headerCells, rowWidth)}
{children && renderTableBody(bodyCells, rowWidth)}
Expand Down
28 changes: 27 additions & 1 deletion src/utils/useScrollListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,31 @@ const useScrollListener = (props: ScrollListenerProps) => {
tableBodyRef
]);

const onScrollByKeydown = useCallback(
(event: React.KeyboardEvent) => {
if (event.currentTarget === event.target) {
event.preventDefault();
const step = 40;

switch (event.key) {
case 'ArrowUp':
onWheel(0, -step);
break;
case 'ArrowDown':
onWheel(0, step);
break;
case 'ArrowLeft':
onWheel(-step, 0);
break;
case 'ArrowRight':
onWheel(step, 0);
break;
}
}
},
[onWheel]
);

useMount(() => {
if (rtl) {
// Initialize scroll position
Expand All @@ -526,7 +551,8 @@ const useScrollListener = (props: ScrollListenerProps) => {
onScrollBody,
onScrollTop,
onScrollLeft,
onScrollTo
onScrollTo,
onScrollByKeydown
};
};

Expand Down
35 changes: 34 additions & 1 deletion test/TableSpec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { render, waitFor, act, fireEvent } from '@testing-library/react';
import { render, waitFor, act, fireEvent, screen } from '@testing-library/react';
import getHeight from 'dom-lib/getHeight';
import getWidth from 'dom-lib/getWidth';
import Table from '../src/Table';
Expand Down Expand Up @@ -1391,4 +1391,37 @@ describe('Table', () => {
expect(width).not.equal(100);
expect(width).to.equal(instance.getBoundingClientRect().width);
});

it('Should call `onScroll` callback when trigger keyboard event', () => {
const onScrollSpy = sinon.spy();
render(
<Table onScroll={onScrollSpy} data={[{ id: 1, name: 'a' }]} height={10} width={100}>
<Column width={100}>
<HeaderCell>11</HeaderCell>
<Cell dataKey="id" />
</Column>
<Column width={100}>
<HeaderCell>11</HeaderCell>
<Cell dataKey="id" />
</Column>
</Table>
);

fireEvent.keyDown(screen.getByRole('grid'), { key: 'ArrowDown' });

expect(onScrollSpy).to.have.been.calledOnce;
expect(onScrollSpy).to.be.calledWith(0, 40);

fireEvent.keyDown(screen.getByRole('grid'), { key: 'ArrowUp' });
expect(onScrollSpy).to.have.been.calledTwice;
expect(onScrollSpy).to.be.calledWith(0, 0);

fireEvent.keyDown(screen.getByRole('grid'), { key: 'ArrowRight' });
expect(onScrollSpy).to.have.been.calledThrice;
expect(onScrollSpy).to.be.calledWith(40, 0);

fireEvent.keyDown(screen.getByRole('grid'), { key: 'ArrowLeft' });
expect(onScrollSpy).to.have.callCount(4);
expect(onScrollSpy).to.be.calledWith(0, 0);
});
});

1 comment on commit bf451a8

@vercel
Copy link

@vercel vercel bot commented on bf451a8 Oct 17, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.