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/stories/Table.stories.tsx b/packages/@react-spectrum/table/stories/Table.stories.tsx index 03fb745c1b5..9ad3841ef26 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: (args) => ( +
+ + + {(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 971f3b8f605..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); @@ -1412,6 +1413,43 @@ describe('TableView', function () { moveFocus('S'); expect(document.activeElement).toBe(getCell(tree, 'Sam')); }); + + describe('type ahead with dialog triggers', 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('does not pick up typeahead from a dialog', function () { + offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get') + .mockImplementationOnce(() => 20) + .mockImplementation(() => 100); + let tree = render(); + 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 () {