From 23f86e987fe6a32579140f9f62d337a593b81ea7 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Mon, 3 Apr 2023 16:57:54 -0700 Subject: [PATCH 1/3] Stop dialog inside collection from closing due to typeahead --- .../selection/src/useTypeSelect.ts | 2 +- .../@react-spectrum/table/test/Table.test.js | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/packages/@react-aria/selection/src/useTypeSelect.ts b/packages/@react-aria/selection/src/useTypeSelect.ts index 19b9a9b0655..51b80dcd675 100644 --- a/packages/@react-aria/selection/src/useTypeSelect.ts +++ b/packages/@react-aria/selection/src/useTypeSelect.ts @@ -53,7 +53,7 @@ export function useTypeSelect(options: AriaTypeSelectOptions): TypeSelectAria { let onKeyDown = (e: KeyboardEvent) => { let character = getStringForKey(e.key); - if (!character || e.ctrlKey || e.metaKey) { + if (!character || e.ctrlKey || e.metaKey || !e.currentTarget.contains(e.target as HTMLElement)) { return; } diff --git a/packages/@react-spectrum/table/test/Table.test.js b/packages/@react-spectrum/table/test/Table.test.js index 971f3b8f605..37d3e517375 100644 --- a/packages/@react-spectrum/table/test/Table.test.js +++ b/packages/@react-spectrum/table/test/Table.test.js @@ -1412,6 +1412,87 @@ describe('TableView', function () { moveFocus('S'); expect(document.activeElement).toBe(getCell(tree, 'Sam')); }); + + describe('', function () { + beforeEach(function () { + offsetHeight.mockRestore(); + offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get') + .mockImplementationOnce(() => 20) + .mockImplementation(() => 100); + }); + afterEach(function () { + offsetHeight.mockRestore(); + offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); + }); + it('wraps around when no items past the current one match', function () { + offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get') + .mockImplementationOnce(() => 20) + .mockImplementation(() => 100); + let columns = [ + {name: 'First Name', id: 'firstname', isRowHeader: true}, + {name: 'Last Name', id: 'lastname', isRowHeader: true}, + {name: 'Birthday', id: 'birthday'}, + {name: 'Edit', id: 'edit'} + ]; + let items = [ + ...Array.from({length: 100}, (v, i) => ({id: i, firstname: 'Aubrey', lastname: 'Sheppard', birthday: 'May 7'})), + {id: 101, firstname: 'John', lastname: 'Doe', birthday: 'May 7'} + ]; + let tree = render( + + + {(col) => ( + {col.name} + )} + + + {(item) => ( + + {(key) => + key === 'edit' ? ( + + + + + + + Add Info + + + + + + + + ) : ( + {item[key]} + ) + } + + )} + + + ); + let trigger = tree.getAllByRole('button')[0]; + triggerPress(trigger); + act(() => { + jest.runAllTimers(); + }); + let textfield = tree.getByLabelText('Enter a J'); + act(() => {textfield.focus();}); + fireEvent.keyDown(textfield, {key: 'J'}); + fireEvent.keyUp(textfield, {key: 'J'}); + act(() => { + jest.runAllTimers(); + }); + expect(document.activeElement).toBe(textfield); + fireEvent.keyDown(document.activeElement, {key: 'Escape'}); + fireEvent.keyUp(document.activeElement, {key: 'Escape'}); + act(() => { + jest.runAllTimers(); + }); + }); + }); }); describe('focus marshalling', function () { From cebf4e0db84393500c05791a720235ecdadb373e Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 4 Apr 2023 09:28:51 -0700 Subject: [PATCH 2/3] make a storybook example --- .../table/stories/Table.stories.tsx | 50 +++++++++++++++++ .../@react-spectrum/table/test/Table.test.js | 53 ++----------------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/packages/@react-spectrum/table/stories/Table.stories.tsx b/packages/@react-spectrum/table/stories/Table.stories.tsx index 03fb745c1b5..c2b1f24264d 100644 --- a/packages/@react-spectrum/table/stories/Table.stories.tsx +++ b/packages/@react-spectrum/table/stories/Table.stories.tsx @@ -1791,3 +1791,53 @@ export const ResizingControlledHideHeader: TableStory = { `}} }; +let typeAheadColumns = [ + {name: 'First Name', id: 'firstname', isRowHeader: true}, + {name: 'Last Name', id: 'lastname', isRowHeader: true}, + {name: 'Birthday', id: 'birthday'}, + {name: 'Edit', id: 'edit'} +]; +let typeAheadRows = [ + ...Array.from({length: 100}, (v, i) => ({id: i, firstname: 'Aubrey', lastname: 'Sheppard', birthday: 'May 7'})), + {id: 101, firstname: 'John', lastname: 'Doe', birthday: 'May 7'} +]; +export const TypeaheadWithDialog: TableStory = { + render: () => ( +
+ + + {(col) => ( + {col.name} + )} + + + {(item) => ( + + {(key) => + key === 'edit' ? ( + + + + + + + Add Info + + + + + + + + ) : ( + {item[key]} + ) + } + + )} + + +
+ ) +} + diff --git a/packages/@react-spectrum/table/test/Table.test.js b/packages/@react-spectrum/table/test/Table.test.js index 37d3e517375..fe1904a84a4 100644 --- a/packages/@react-spectrum/table/test/Table.test.js +++ b/packages/@react-spectrum/table/test/Table.test.js @@ -36,7 +36,8 @@ import userEvent from '@testing-library/user-event'; let { InlineDeleteButtons: DeletableRowsTable, EmptyStateStory: EmptyStateTable, - WithBreadcrumbNavigation: TableWithBreadcrumbs + WithBreadcrumbNavigation: TableWithBreadcrumbs, + TypeaheadWithDialog: TypeaheadWithDialog } = composeStories(stories); @@ -1413,7 +1414,7 @@ describe('TableView', function () { expect(document.activeElement).toBe(getCell(tree, 'Sam')); }); - describe('', function () { + describe('type ahead with dialog triggers', function () { beforeEach(function () { offsetHeight.mockRestore(); offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get') @@ -1424,55 +1425,11 @@ describe('TableView', function () { offsetHeight.mockRestore(); offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); }); - it('wraps around when no items past the current one match', function () { + it('does not pick up typeahead from a dialog', function () { offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get') .mockImplementationOnce(() => 20) .mockImplementation(() => 100); - let columns = [ - {name: 'First Name', id: 'firstname', isRowHeader: true}, - {name: 'Last Name', id: 'lastname', isRowHeader: true}, - {name: 'Birthday', id: 'birthday'}, - {name: 'Edit', id: 'edit'} - ]; - let items = [ - ...Array.from({length: 100}, (v, i) => ({id: i, firstname: 'Aubrey', lastname: 'Sheppard', birthday: 'May 7'})), - {id: 101, firstname: 'John', lastname: 'Doe', birthday: 'May 7'} - ]; - let tree = render( - - - {(col) => ( - {col.name} - )} - - - {(item) => ( - - {(key) => - key === 'edit' ? ( - - - - - - - Add Info - - - - - - - - ) : ( - {item[key]} - ) - } - - )} - - - ); + let tree = render(); let trigger = tree.getAllByRole('button')[0]; triggerPress(trigger); act(() => { From f512ca8ac2c518f1d494e135443dfdd426b96426 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 4 Apr 2023 13:39:09 -0700 Subject: [PATCH 3/3] fix lint --- packages/@react-spectrum/table/stories/Table.stories.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@react-spectrum/table/stories/Table.stories.tsx b/packages/@react-spectrum/table/stories/Table.stories.tsx index c2b1f24264d..9ad3841ef26 100644 --- a/packages/@react-spectrum/table/stories/Table.stories.tsx +++ b/packages/@react-spectrum/table/stories/Table.stories.tsx @@ -1802,9 +1802,9 @@ let typeAheadRows = [ {id: 101, firstname: 'John', lastname: 'Doe', birthday: 'May 7'} ]; export const TypeaheadWithDialog: TableStory = { - render: () => ( + render: (args) => (
- + {(col) => ( {col.name} @@ -1839,5 +1839,5 @@ export const TypeaheadWithDialog: TableStory = {
) -} +};