Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/react-aria-components/test/ListBox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2523,6 +2523,39 @@ describe('keyboard modifier keys', () => {
expect(document.activeElement).toBe(options[1]);
});

it('does not activate an element focused during selection with Enter', async () => {
let onClick = jest.fn();
let triggerRef = React.createRef();
let {getByRole} = render(
<>
<button ref={triggerRef} onClick={onClick}>
Trigger
</button>
<ListBox
aria-label="Favorite Animal"
selectionMode="single"
onSelectionChange={() => {
// oxlint-disable-next-line rsp-rules/act-events-test
triggerRef.current.focus();
}}>
<ListBoxItem id="cat">Cat</ListBoxItem>
<ListBoxItem id="dog">Dog</ListBoxItem>
</ListBox>
</>
);

let options = within(getByRole('listbox')).getAllByRole('option');
act(() => options[0].focus());

// Selection moves focus to the trigger during keydown. Unless Enter's default is
// prevented, the browser dispatches the activation click to the newly focused
// element.
await user.keyboard('{Enter}');

expect(triggerRef.current).toHaveFocus();
expect(onClick).not.toHaveBeenCalled();
});

describe('multiple selection, replace behavior', () => {
it('replaces selection as focus moves with arrow keys', async () => {
let onSelectionChange = jest.fn();
Expand Down
14 changes: 9 additions & 5 deletions packages/react-aria/src/interactions/usePress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ export function usePress(props: PressHookProps): PressResult {
isValidKeyboardEvent(e.nativeEvent, e.currentTarget as Element) &&
nodeContains(e.currentTarget as Element, getEventTarget(e) as Element)
) {
if (shouldPreventDefaultKeyboard(getEventTarget(e) as Element, e.key)) {
if (shouldPreventDefaultKeyboard(getEventTarget(e) as Element, e)) {
e.preventDefault();
}

Expand Down Expand Up @@ -497,7 +497,7 @@ export function usePress(props: PressHookProps): PressResult {

let onKeyUp = (e: KeyboardEvent) => {
if (state.isPressed && state.target && isValidKeyboardEvent(e, state.target)) {
if (shouldPreventDefaultKeyboard(getEventTarget(e) as Element, e.key)) {
if (shouldPreventDefaultKeyboard(getEventTarget(e) as Element, e)) {
e.preventDefault();
}

Expand Down Expand Up @@ -1161,9 +1161,13 @@ function shouldPreventDefaultUp(target: Element) {
return true;
}

function shouldPreventDefaultKeyboard(target: Element, key: string) {
// Don't prevent the contextmenu shortcut on mac.
if (isMac() && key === 'Enter') {
function shouldPreventDefaultKeyboard(
target: Element,
event: Pick<KeyboardEvent, 'key' | 'ctrlKey'>
) {
let {key} = event;
// Don't prevent the contextmenu shortcut (Control + Enter) on mac.
if (isMac() && key === 'Enter' && event.ctrlKey) {
return false;
}

Expand Down
23 changes: 23 additions & 0 deletions packages/react-aria/test/interactions/usePress.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3173,6 +3173,29 @@ describe('usePress', function () {
]);
});

it('should prevent default on Enter on macOS', function () {
let {getByText} = render(<Example />);
using spy = jest.spyOn(window.navigator, 'platform', 'get').mockImplementation(() => 'Mac');

let el = getByText('test');
let allowDefault = fireEvent.keyDown(el, {key: 'Enter'});
expect(allowDefault).toBe(false);
allowDefault = fireEvent.keyUp(el, {key: 'Enter'});
expect(allowDefault).toBe(false);
spy.mockRestore();
});

it('should not prevent default on Control + Enter on macOS so the context menu can open', function () {
let {getByText} = render(<Example />);
using spy = jest.spyOn(window.navigator, 'platform', 'get').mockImplementation(() => 'Mac');

let el = getByText('test');
let allowDefault = fireEvent.keyDown(el, {key: 'Enter', ctrlKey: true});
expect(allowDefault).toBe(true);
fireEvent.keyUp(el, {key: 'Enter', ctrlKey: true});
spy.mockRestore();
});

it('should handle when focus moves between keydown and keyup', function () {
let events = [];
let addEvent = e => events.push(e);
Expand Down
Loading