fix(GridLayout): support RTL direction for drop target positioning#9848
fix(GridLayout): support RTL direction for drop target positioning#9848miguelcalderon wants to merge 3 commits intoadobe:mainfrom
Conversation
GridLayout.getDropTargetFromPoint() computes 'before'/'after' drop positions
using x-coordinates, but has no awareness of layout direction. In RTL locales,
the Virtualizer positions items using CSS 'right' with the layout rect's x
value as the right-offset, while pointer coordinates remain in visual
(left-origin) space. This mismatch causes drop targets to be inverted —
dragging an item to the right of another shows a 'before' indicator instead
of 'after'.
This commit adds an optional 'direction' property to GridLayoutOptions.
When set to 'rtl', getDropTargetFromPoint flips the x-coordinate to match
the layout coordinate system before computing drop positions.
Consumers can pass direction via useLayoutOptions() in a GridLayout subclass:
class LocaleAwareGridLayout extends GridLayout {
useLayoutOptions() {
const { direction } = useLocale();
return { direction };
}
}
|
Sign CLA |
Tests getDropTargetFromPoint with both LTR and RTL directions to verify that drop targets (before/after) are computed correctly in multi-column grids. Also tests that single-column layouts are unaffected by direction and that empty layouts return a root drop target.
|
@LFDanLu This should probably also be done for the horizontal list layout. I'm also wondering whether class LocaleAwareGridLayout extends GridLayout {
useLayoutOptions() {
const { direction } = useLocale();
return { direction };
}
}should be done by default in both Grid and ListLayout, similar to table layout internals. Alternatively, we could also consider pushing all of this into |
|
Thanks for catching this issue @miguelcalderon, I'll see about taking a closer look soon. @nwidynski Yep this will definitely need to be added to the horizontal ListLayout as well. At a glance I think making the layouts automatically determine locale makes sense, but mind expanding on the |
|
I mean, all this PR really does is to align the coordinate space of event targets (which is always left-right) with the one of our layout (which is locale-aware due to VirtualizerItem). I think it should be possible to do this alignment before passing x,y into Since our non-virtualized scenario is locale-aware though (see ListDropTargetDelegate), we would probably have trouble differentiating between those - so likely preferable to auto-determine as discussed. |
Instead of requiring consumers to subclass GridLayout and pass direction manually, create a RAC wrapper (like TableLayout) that calls useLocale() internally via useLayoutOptions(). The base layout in react-stately still accepts direction as an explicit option for non-RAC consumers.
|
Good call on auto-determining direction — I've added a RAC wrapper for GridLayout that calls The base layout in |
Description
GridLayout.getDropTargetFromPoint()computesbefore/afterdrop positions using x-coordinates but has no awareness of layout direction. In RTL locales the Virtualizer positions items using CSSrightwith the layout rect's x value as the right-offset, while pointer coordinates remain in visual (left-origin) space. This causes drop targets to be inverted — dragging an item to the right of another shows abeforeindicator instead ofafter.Changes
directionproperty toGridLayoutOptions('ltr' | 'rtl', default'ltr').'rtl',getDropTargetFromPointflips the x-coordinate to match the layout coordinate system before computing drop positions.directiontoshouldInvalidateLayoutOptionsso layout updates when direction changes.Usage
Consumers pass
directionviauseLayoutOptions()in aGridLayoutsubclass:✅ Pull Request Checklist:
📝 Test Instructions:
if (this.direction === 'rtl' ...)block inGridLayout.ts— the 2 RTL tests should fail while LTR tests continue to pass.Notes
ListLayoutis not affected since it is single-column.'ltr'which preserves existing behavior.🧢 Your Project:
Nutrient (formerly PSPDFKit) — baseline-ui component library