-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix virtualizer persisted keys with drag and drop #6644
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that within the 'Drag within table many items' story, if you mouse drag an item from the top of the list to the bottom, then try to keyboard drag an item back up, the list doesn't scroll as you move the drop indicator up the list.
Hmm yeah that seems to be an issue with persisted keys in TableLayout... |
Ok fixed 3 issues:
|
Brain dump before break: Actually I did manage to reproduce (2) in RSP as well, so we should persist the drag target as well as the drop target. It only occurs when the drag target element is removed from the dom and not reused by another view, most commonly with variable row heights. The other issue with scrolling to the top on drop also only seems to occur in the non-util handlers stories, I think because the |
// i.e. When you from one list to another during a drag session, we need the blur to fire on the first list after the drag. | ||
if (!this.dragTarget.element.contains(this.currentDropTarget.element)) { | ||
this.dragTarget.element.dispatchEvent(new FocusEvent('blur')); | ||
this.dragTarget.element.dispatchEvent(new FocusEvent('focusout', {bubbles: true})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary since we do allow focus events to propagate to the drag target (in cancelEvent
above)
This reverts commit 1802c1c.
06436b6
to
9743bf1
Compare
## API Changes
unknown top level export { type: 'any' } @react-aria/virtualizerVirtualizer Virtualizer<O, T extends {}, V extends ReactNode> {
children: (string, {}) => ReactNode
collection: Collection<{}>
- focusedKey?: Key
isLoading?: boolean
layout: Layout<{}, O>
layoutOptions?: O
onLoadMore?: () => void
+ persistedKeys?: Set<Key> | null
renderWrapper?: RenderWrapper<{}, ReactNode>
scrollDirection?: 'horizontal' | 'vertical' | 'both'
sizeToFit?: 'width' | 'height'
} @react-stately/layoutGridLayout GridLayout<O = any, T> {
constructor: (GridLayoutOptions) => void
getContentSize: () => Size
getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
getLayoutInfo: (Key) => LayoutInfo | null
getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
- validate: () => void
+ update: () => void
} ListLayout ListLayout<O = any, T> {
constructor: (ListLayoutOptions) => void
getContentSize: () => void
getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
getLayoutInfo: (Key) => void
getVisibleLayoutInfos: (Rect) => void
+ update: (InvalidationContext<O>) => void
updateItemSize: (Key, Size) => void
- validate: (InvalidationContext<O>) => void
} TableLayout TableLayout<O extends TableLayoutProps = TableLayoutProps, T> {
constructor: (ListLayoutOptions) => void
getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
getVisibleLayoutInfos: (Rect) => void
- validate: (InvalidationContext<TableLayoutProps>) => void
+ update: (InvalidationContext<TableLayoutProps>) => void
} @react-stately/virtualizerLayout Layout<O = any, T extends {}> {
getContentSize: () => Size
getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
getItemRect: (Key) => Rect
getLayoutInfo: (Key) => LayoutInfo | null
getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
getVisibleRect: () => Rect
shouldInvalidate: (Rect, Rect) => boolean
+ update: (InvalidationContext<O>) => void
updateItemSize: (Key, Size) => boolean
- validate: (InvalidationContext<O>) => void
virtualizer: Virtualizer<{}, any>
} |
In all versions,
Those are the only issues I've found so far, and they aren't that big of issues. Tested on Chrome and Safari, keyboard and mouse, RAC and RSP. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Giving an approval for now, will continue with testing. It'd be good if others can test other combinations.
Looks like this was the case before as well. Probably due to scroll into view only occurring in keyboard modality...
This is strange, but the behavior is better than before where it didn't scroll at all. 😂 |
Depends on #6640
This fixes the virtualizer
persistedKeys
during drag and drop so that keyboard navigation works correctly and focus isn't lost. Since we only render one of the drop positions (before or after), we need to normalize the key we persist accordingly so the correct one is in the DOM and able to get focus.I've also changed the API on Virtualizer and collection renderers in general to accept
persistedKeys
as a prop rather than a singlefocusedKey
. This enables multiple keys to be persisted and is more extensible for future use cases.Finally, based on feedback in #6631 (comment), I've renamed the Layout
validate
method toupdate
to make it easier to understand. This was originally pulled from v2 CollectionView but since we are doing a breaking change we can rename it now.Test instructions: