Skip to content
Open
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
3 changes: 3 additions & 0 deletions packages/@react-aria/dnd/src/DragManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,9 @@ class DragSession {
this.dragTarget.element.focus();
}

// Re-trigger focus event on active element, since it will not have received it during dragging (see cancelEvent).
document.activeElement?.dispatchEvent(new FocusEvent('focusin', {bubbles: true}));

announce(this.stringFormatter.format('dropCanceled'));
}

Expand Down
77 changes: 77 additions & 0 deletions packages/react-aria-components/stories/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,83 @@ DndTableExample.args = {
isLoading: false
};

function DndTableWithNoValidDropTargetsRender(): JSX.Element {
let list = useListData({
initialItems: [
{id: '1', type: 'file', name: 'Adobe Photoshop'},
{id: '2', type: 'file', name: 'Adobe XD'},
{id: '3', type: 'folder', name: 'Documents'},
{id: '4', type: 'file', name: 'Adobe InDesign'},
{id: '5', type: 'folder', name: 'Utilities'},
{id: '6', type: 'file', name: 'Adobe AfterEffects'}
]
});

let {dragAndDropHooks} = useDragAndDrop({
getItems(keys) {
return [...keys].filter(k => !!list.getItem(k)).map((key) => {
let item = list.getItem(key);
return {
'custom-app-type': JSON.stringify(item),
'text/plain': item!.name
};
});
},
onItemDrop() {},
shouldAcceptItemDrop() {
return false;
}
});

return (
<Table
aria-label="Table (rejects all item drops)"
selectionMode="multiple"
selectedKeys={list.selectedKeys}
onSelectionChange={list.setSelectedKeys}
dragAndDropHooks={dragAndDropHooks}>
<TableHeader>
<Column />
<Column><MyCheckbox slot="selection" /></Column>
<Column>ID</Column>
<Column isRowHeader>Name</Column>
<Column>Type</Column>
</TableHeader>
<TableBody items={list.items}>
<Collection items={list.items}>
{item => (
<Row>
<Cell><Button slot="drag">≡</Button></Cell>
<Cell><MyCheckbox slot="selection" /></Cell>
<Cell>{item.id}</Cell>
<Cell>{item.name}</Cell>
<Cell>{item.type}</Cell>
</Row>
)}
</Collection>
</TableBody>
</Table>
);
}

export const DndTableWithNoValidDropTargets: TableStoryObj = {
render: DndTableWithNoValidDropTargetsRender,
name: 'Dnd Table with no valid drop targets',
parameters: {
description: {
data: `Tests that arrow keys work after canceling a keyboard drag when shouldAcceptItemDrop rejects all drop targets.
Test Instructions:
1. Focus on an item's drag button
2. Press Enter to start keyboard drag
3. Notice there are no valid drop targets (shouldAcceptItemDrop rejects all item drops)
4. Press Escape to cancel the drag
5. Try pressing arrow keys
6. Observe that focus moves (and we've exited virtual drag mode)
`
}
}
};

export const MyCheckbox = ({children, ...props}: CheckboxProps) => {
return (
<Checkbox {...props}>
Expand Down