Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
70 changes: 70 additions & 0 deletions packages/react-aria-components/test/Table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ import {DataTransfer, DragEvent} from 'react-aria/test/dnd/mocks';
import {Dialog, DialogTrigger} from '../src/Dialog';
import {DropIndicator, useDragAndDrop} from '../src/useDragAndDrop';
import {Label} from '../src/Label';
import {ListBox, ListBoxItem} from '../src/ListBox';
import {Modal} from '../src/Modal';
import {Popover} from '../src/Popover';
import React, {useMemo, useState} from 'react';
import {resizingTests} from 'react-aria/test/table/tableResizingTests.tsx';
import {Select, SelectValue} from '../src/Select';
import {setInteractionModality} from 'react-aria/private/interactions/useFocusVisible';
import * as stories from '../stories/Table.stories';
import {TableLayout} from '../src/TableLayout';
Expand Down Expand Up @@ -1167,10 +1170,77 @@ describe('Table', () => {

await user.tab();
expect(document.activeElement).toBe(rowElements[1]);
await user.keyboard('{ArrowRight}');
Comment thread
snowystinger marked this conversation as resolved.
Outdated
await user.keyboard('boo');
expect(document.activeElement).toBe(rowElements[3]);
});

it('should select inside a cell using typeahead before the table takes over typeahead', async () => {
let rows = [
{id: 1, name: '1. Games', date: '6/7/2020', type: 'File folder', textValue: 'Games'},
{id: 2, name: '2. Program Files', date: '4/7/2021', type: 'File folder', textValue: 'Program Files'},
{id: 3, name: '3. bootmgr', date: '11/20/2010', type: 'System file', textValue: 'bootmgr'},
{id: 4, name: '4. log.txt', date: '1/18/2016', type: 'Text Document', textValue: 'log.txt'}
];
let {getAllByRole} = render(
<Table aria-label="Files">
<MyTableHeader columns={columns}>
{column => (
<MyColumn isRowHeader={column.isRowHeader} childColumns={column.children}>
{column.name}
</MyColumn>
)}
</MyTableHeader>
<TableBody items={rows}>
{item => (
<MyRow columns={columns} textValue={item.textValue}>
{column => {
if (column.id !== 'name') {
return (
<Cell>
<div>
{item[column.id]}
</div>
</Cell>
);
}
return (
<Cell>
<div>
{item[column.id]}
<Select aria-label="Select">
<Button>
<SelectValue />
</Button>
<Popover>
<ListBox>
<ListBoxItem>abc</ListBoxItem>
<ListBoxItem>boo</ListBoxItem>
<ListBoxItem>ghi</ListBoxItem>
</ListBox>
</Popover>
</Select>
</div>
</Cell>
);
}}
</MyRow>
)}
</TableBody>
</Table>
);
let rowElements = getAllByRole('row');

await user.tab();
expect(document.activeElement).toBe(rowElements[1]);
await user.keyboard('{ArrowRight}');
let select = within(rowElements[1]).getByRole('button');
expect(document.activeElement).toBe(select);
await user.keyboard('boo');
expect(document.activeElement).toBe(select);
expect(select).toHaveTextContent('boo');
});

it('should support updating columns', () => {
let tree = render(
<DynamicTable
Expand Down
18 changes: 12 additions & 6 deletions packages/react-aria/src/actiongroup/useActionGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,30 @@ export function useActionGroup<T>(
let {keyboardProps} = useKeyboard({
shortcuts: {
ArrowRight: () => {
let next;
if (flipDirection) {
focusManager.focusPrevious({wrap: true});
next = focusManager.focusPrevious({wrap: true, action: 'ArrowRight'});
} else {
focusManager.focusNext({wrap: true});
next = focusManager.focusNext({wrap: true, action: 'ArrowRight'});
}
return next !== null;
},
ArrowDown: () => {
focusManager.focusNext({wrap: true});
let next = focusManager.focusNext({wrap: true, action: 'ArrowDown'});
return next !== null;
},
ArrowLeft: () => {
let next;
if (flipDirection) {
focusManager.focusNext({wrap: true});
next = focusManager.focusNext({wrap: true, action: 'ArrowLeft'});
} else {
focusManager.focusPrevious({wrap: true});
next = focusManager.focusPrevious({wrap: true, action: 'ArrowLeft'});
}
return next !== null;
},
ArrowUp: () => {
focusManager.focusPrevious({wrap: true});
let next = focusManager.focusPrevious({wrap: true, action: 'ArrowUp'});
return next !== null;
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion packages/react-aria/src/dnd/DragManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class DragSession {
this.restoreAriaHidden?.();
}

onKeyDown(e: KeyboardEvent): void {
onKeyDown(e: KeyboardEvent): void { // TODO: should these be stopped?
this.cancelEvent(e);

if (e.key === 'Escape') {
Expand Down
18 changes: 18 additions & 0 deletions packages/react-aria/src/focus/FocusScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export interface FocusScopeProps {
}

export interface FocusManagerOptions {
/** The action that triggered the focus movement. */
action?: string,
/** The element to start searching from. The currently focused element by default. */
from?: Element;
/** Whether to only include tabbable elements, or all focusable elements. */
Expand Down Expand Up @@ -921,6 +923,14 @@ export function createFocusManager(
if (!nextNode && wrap) {
walker.currentNode = root;
nextNode = walker.nextNode() as FocusableElement;
if (nextNode) {
let event = new CustomEvent('focus-manager-focus-wrap', {bubbles: true, cancelable: true, detail: {action: opts.action}});
let target = from || getActiveElement(getOwnerDocument(root))!;
target.dispatchEvent(event);
if (event.defaultPrevented) {
return null;
}
}
}
if (nextNode) {
focusElement(nextNode, true);
Expand Down Expand Up @@ -958,6 +968,14 @@ export function createFocusManager(
return null;
}
previousNode = lastNode;
if (previousNode) {
let event = new CustomEvent('focus-manager-focus-wrap', {bubbles: true, cancelable: true, detail: {action: opts.action}});
let target = from || getActiveElement(getOwnerDocument(root))!;
target.dispatchEvent(event);
if (event.defaultPrevented) {
return null;
}
}
}
if (previousNode) {
focusElement(previousNode, true);
Expand Down
3 changes: 3 additions & 0 deletions packages/react-aria/src/grid/useGridCell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ export function useGridCell<T, C extends GridCollection<T>>(
isDisabled: state.collection.size === 0
});

// TODO: decide move away from capturing. We may not want to because it
// prevents events from reaching content of cells, which can't have interactive children anyways.
// So by preventing them, users are alerted to the fact that this isn't an allowed pattern.
let onKeyDownCapture = (e: ReactKeyboardEvent) => {
let activeElement = getActiveElement();
if (
Expand Down
Loading