From eb2855b1b7fb379f5996f98fbaf67a0cc3924509 Mon Sep 17 00:00:00 2001
From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Date: Fri, 7 Aug 2026 10:53:51 -0700
Subject: [PATCH 1/2] fix: Scroll GridList to focused drop indicators
Fixes #6492
---
.../react-aria-components/src/GridList.tsx | 1 +
.../test/GridList.browser.test.tsx | 61 +++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/packages/react-aria-components/src/GridList.tsx b/packages/react-aria-components/src/GridList.tsx
index 22ea560aef6..f78c9c574be 100644
--- a/packages/react-aria-components/src/GridList.tsx
+++ b/packages/react-aria-components/src/GridList.tsx
@@ -769,6 +769,7 @@ function GridListDropIndicator(props: GridListDropIndicatorProps, ref: Forwarded
let renderProps = useRenderProps({
...otherProps,
defaultClassName: 'react-aria-DropIndicator',
+ defaultStyle: {position: 'relative'},
values: {
isDropTarget
}
diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx
index a8f13c11242..8cc6a88d062 100644
--- a/packages/react-aria-components/test/GridList.browser.test.tsx
+++ b/packages/react-aria-components/test/GridList.browser.test.tsx
@@ -10,6 +10,8 @@
* governing permissions and limitations under the License.
*/
+import {Button} from '../src/Button';
+import {DropIndicator, useDragAndDrop} from '../src/useDragAndDrop';
import {expect, it} from 'vitest';
import {GridLayout} from '../src/GridLayout';
import {GridList, GridListItem} from '../src/GridList';
@@ -17,8 +19,36 @@ import React, {useState} from 'react';
import {render} from 'vitest-browser-react';
import {Size} from 'react-stately/useVirtualizerState';
import {User} from '@react-aria/test-utils';
+import {userEvent} from 'vitest/browser';
import {Virtualizer} from '../src/Virtualizer';
+const reorderableItems = Array.from({length: 10}, (_, i) => ({id: i, name: `Item ${i}`}));
+
+function ReorderableGridList() {
+ let {dragAndDropHooks} = useDragAndDrop({
+ getItems: keys => [...keys].map(key => ({'text/plain': String(key)})),
+ onReorder() {},
+ renderDropIndicator: target => (
+
+ )
+ });
+
+ return (
+
+ {item => (
+
+
+ {item.name}
+
+ )}
+
+ );
+}
+
function Grid() {
return (
{
await button.click();
await expect(tester.getRows().length).toBeGreaterThan(0);
});
+
+it('scrolls focused drop indicators into view during keyboard reordering', async () => {
+ let {container} = await render();
+ let gridlist = container.querySelector('[role=grid]') as HTMLElement;
+ let dragButton = container.querySelector('[aria-label="Drag Item 0"]') as HTMLElement;
+ dragButton.focus();
+
+ await userEvent.keyboard('{Enter}');
+
+ for (let i = 1; i <= 4; i++) {
+ await userEvent.keyboard('{ArrowDown}');
+ let dropIndicator = document.activeElement as HTMLElement;
+ let indicatorRow = dropIndicator.closest('[role=row]') as HTMLElement;
+ let gridRect = gridlist.getBoundingClientRect();
+ let indicatorRect = dropIndicator.getBoundingClientRect();
+
+ expect(dropIndicator).toHaveAttribute(
+ 'aria-label',
+ `Insert between Item ${i} and Item ${i + 1}`
+ );
+ expect(dropIndicator).toHaveAttribute('role', 'button');
+ expect(indicatorRow).toHaveStyle({
+ backgroundColor: 'rgb(255, 0, 0)',
+ position: 'relative'
+ });
+ expect(indicatorRect.top).toBeGreaterThanOrEqual(gridRect.top);
+ expect(indicatorRect.bottom).toBeLessThanOrEqual(gridRect.bottom);
+ }
+
+ expect(gridlist.scrollTop).toBeGreaterThan(0);
+});
From c3c13317605c54495c7a0c5854b07f90cec1065e Mon Sep 17 00:00:00 2001
From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Date: Sat, 8 Aug 2026 07:32:12 -0700
Subject: [PATCH 2/2] test: fix lint violation and measure the indicator row in
scroll assertion
---
packages/react-aria-components/test/GridList.browser.test.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx
index 8cc6a88d062..4d5daa4c184 100644
--- a/packages/react-aria-components/test/GridList.browser.test.tsx
+++ b/packages/react-aria-components/test/GridList.browser.test.tsx
@@ -27,7 +27,7 @@ const reorderableItems = Array.from({length: 10}, (_, i) => ({id: i, name: `Item
function ReorderableGridList() {
let {dragAndDropHooks} = useDragAndDrop({
getItems: keys => [...keys].map(key => ({'text/plain': String(key)})),
- onReorder() {},
+ onReorder: () => undefined,
renderDropIndicator: target => (
)
@@ -164,7 +164,7 @@ it('scrolls focused drop indicators into view during keyboard reordering', async
let dropIndicator = document.activeElement as HTMLElement;
let indicatorRow = dropIndicator.closest('[role=row]') as HTMLElement;
let gridRect = gridlist.getBoundingClientRect();
- let indicatorRect = dropIndicator.getBoundingClientRect();
+ let indicatorRect = indicatorRow.getBoundingClientRect();
expect(dropIndicator).toHaveAttribute(
'aria-label',