Skip to content

Commit 65de580

Browse files
authored
fix(AnalyticalTable): allow selecting all rows via keyboard (#6168)
Fixes #6110
1 parent 656ad5a commit 65de580

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ describe('AnalyticalTable', () => {
623623
cy.findByTestId('payloadRowsById').should('have.text', '{"1":true,"2":true,"3":false}');
624624
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'false');
625625

626+
//select all
627+
//click
626628
cy.get('[data-row-index="0"][data-column-index="0"]').click();
627629
cy.get('@onRowSelectSpy').should('have.callCount', 6);
628630
cy.findByTestId('payload').should(
@@ -635,6 +637,33 @@ describe('AnalyticalTable', () => {
635637
);
636638
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'true');
637639

640+
// enter (keydown)
641+
cy.get('[data-row-index="0"][data-column-index="0"]').realPress('Enter');
642+
cy.get('@onRowSelectSpy').should('have.callCount', 7);
643+
cy.findByTestId('payload').should('have.text', '[]');
644+
cy.findByTestId('payloadRowsById').should('have.text', '{}');
645+
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'false');
646+
647+
// Space (keyup) + ArrowDown => 1st row selected
648+
cy.get('[data-row-index="0"][data-column-index="0"]').realPress(['Space', 'ArrowDown']);
649+
cy.get('@onRowSelectSpy').should('have.callCount', 8);
650+
cy.findByTestId('payload').should('have.text', '["0"]');
651+
cy.findByTestId('payloadRowsById').should('have.text', '{"0":true}');
652+
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'false');
653+
654+
// Space (keyup) + ArrowUp => all rows selected
655+
cy.get('[data-row-index="0"][data-column-index="0"]').realPress(['Space', 'ArrowUp']);
656+
cy.get('@onRowSelectSpy').should('have.callCount', 9);
657+
cy.findByTestId('payload').should(
658+
'have.text',
659+
'["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"]'
660+
);
661+
cy.findByTestId('payloadRowsById').should(
662+
'have.text',
663+
'{"0":true,"1":true,"2":true,"3":true,"4":true,"5":true,"6":true,"7":true,"8":true,"9":true,"10":true,"11":true,"12":true,"13":true,"14":true,"15":true,"16":true,"17":true,"18":true,"19":true,"20":true}'
664+
);
665+
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'true');
666+
638667
cy.get('[data-row-index="0"][data-column-index="0"]').click();
639668

640669
cy.findByText('Name-0').click();
@@ -647,7 +676,7 @@ describe('AnalyticalTable', () => {
647676
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'false');
648677

649678
cy.get('[data-row-index="0"][data-column-index="0"]').click();
650-
cy.get('@onRowSelectSpy').should('have.callCount', 11);
679+
cy.get('@onRowSelectSpy').should('have.callCount', 14);
651680
cy.findByTestId('payload').should('have.text', '["0","1","5","7","17","20"]');
652681
cy.findByTestId('payloadRowsById').should('have.text', '{"0":true,"1":true,"5":true,"7":true,"17":true,"20":true}');
653682
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'false');
@@ -702,7 +731,7 @@ describe('AnalyticalTable', () => {
702731
'{"0":true,"1":true,"2":true,"3":true,"4":true,"5":true,"6":true,"7":true,"8":true,"9":true,"10":true,"11":true,"12":true,"13":true,"14":true,"15":true,"16":true,"17":true,"18":true,"19":true,"20":true}'
703732
);
704733
cy.findByTestId('payloadAllRowsSelected').should('have.text', 'true');
705-
cy.get('@onRowSelectSpy').should('have.callCount', 16);
734+
cy.get('@onRowSelectSpy').should('have.callCount', 19);
706735
});
707736

708737
it('row & header height', () => {

packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export interface ColumnHeaderProps {
4444
id: string;
4545
onClick: MouseEventHandler<HTMLDivElement> | undefined;
4646
onKeyDown?: KeyboardEventHandler<HTMLDivElement> | undefined;
47+
onKeyUp?: KeyboardEventHandler<HTMLDivElement> | undefined;
4748
className: string;
4849
style: CSSProperties;
4950
column: ColumnType;
@@ -80,6 +81,7 @@ export const ColumnHeader = (props: ColumnHeaderProps) => {
8081
visibleColumnIndex,
8182
onClick,
8283
onKeyDown,
84+
onKeyUp,
8385
isFiltered,
8486
title,
8587
'aria-label': ariaLabel,
@@ -131,7 +133,9 @@ export const ColumnHeader = (props: ColumnHeaderProps) => {
131133
const hasPopover = column.canGroupBy || column.canSort || column.canFilter;
132134

133135
const handleHeaderCellClick = (e) => {
134-
onClick?.(e);
136+
if (typeof onClick === 'function') {
137+
onClick(e);
138+
}
135139
if (hasPopover) {
136140
setPopoverOpen(true);
137141
}
@@ -142,7 +146,9 @@ export const ColumnHeader = (props: ColumnHeaderProps) => {
142146
: { left: 0, transform: `translateX(${virtualColumn.start}px)` };
143147

144148
const handleHeaderCellKeyDown = (e) => {
145-
onKeyDown?.(e);
149+
if (typeof onKeyDown === 'function') {
150+
onKeyDown(e);
151+
}
146152
if (hasPopover && e.code === 'Enter') {
147153
setPopoverOpen(true);
148154
}
@@ -152,6 +158,9 @@ export const ColumnHeader = (props: ColumnHeaderProps) => {
152158
};
153159

154160
const handleHeaderCellKeyUp = (e) => {
161+
if (typeof onKeyUp === 'function') {
162+
onKeyUp(e);
163+
}
155164
if (hasPopover && e.code === 'Space' && !e.target.hasAttribute('ui5-li')) {
156165
setPopoverOpen(true);
157166
}

packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ function getPayload(e, column) {
349349
const setHeaderProps = (headerProps, { instance: { dispatch }, column }) => {
350350
// resize col with keyboard
351351
const handleKeyDown = (e) => {
352+
if (typeof headerProps.onKeyDown === 'function') {
353+
headerProps.onKeyDown(e);
354+
}
352355
if (e.nativeEvent.shiftKey) {
353356
if (e.key === 'ArrowRight') {
354357
const payload = getPayload(e, column);

packages/main/src/components/AnalyticalTable/hooks/useRowSelectionColumn.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import type { ReactTableHooks } from '../types/index.js';
66

77
const customCheckBoxStyling = {
88
verticalAlign: 'middle',
9-
pointerEvents: 'none'
9+
pointerEvents: 'none',
10+
display: 'block'
1011
} as CSSProperties;
1112

1213
/*
@@ -78,6 +79,9 @@ const headerProps = (props, { instance }) => {
7879
selectionMode === AnalyticalTableSelectionMode.Multiple
7980
) {
8081
const onClick = (e) => {
82+
if (typeof props.onClick === 'function') {
83+
props.onClick(e);
84+
}
8185
toggleAllRowsSelected(!isAllRowsSelected);
8286
const isFiltered = filters?.length > 0 || !!globalFilter;
8387
if (typeof onRowSelect === 'function') {
@@ -97,6 +101,9 @@ const headerProps = (props, { instance }) => {
97101
};
98102

99103
const onKeyDown = (e) => {
104+
if (typeof props.onKeyDown === 'function') {
105+
props.onKeyDown(e);
106+
}
100107
if (e.code === 'Enter' || e.code === 'Space') {
101108
e.preventDefault();
102109
if (e.code === 'Enter') {
@@ -106,6 +113,9 @@ const headerProps = (props, { instance }) => {
106113
};
107114

108115
const onKeyUp = (e) => {
116+
if (typeof props.onKeyUp === 'function') {
117+
props.onKeyUp(e);
118+
}
109119
if (e.code === 'Space') {
110120
e.preventDefault();
111121
onClick(e);

0 commit comments

Comments
 (0)