list: Add drag and drop support to ListItem - #2553
Closed
lijingrs wants to merge 8 commits into
Closed
Conversation
Add on_drag, on_drop, and on_drag_hover methods to ListItem that delegate to the underlying base div. This enables drag-and-drop reordering when ListItem is used inside a Tree or custom list layout. The methods follow the same builder pattern as the existing on_click and on_mouse_down methods.
Member
|
Please at least add simple example for this API in to story. |
- Add DragPreview entity for drag preview rendering - Add with_drag_drop method to CompanyListItem demonstrating on_drag/on_drop/on_drag_hover usage - Add draggable checkbox to enable/disable drag-and-drop demo - Console output shows drag-over and drop events for easy testing This addresses the PR review request for a simple example of the drag-and-drop API. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Fix type annotations for on_drag and on_drop closures - Change method to use mutable self instead of chained calls - Mark unused _cx parameter in render_item - Separate clone variables for each drag handler to avoid conflicts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Fix self.base.base chain that was causing syntax error - Properly format on_drop call as single line with correct parameter types Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add explicit type annotations for all closure cx parameters: "&mut App" - Fix self.base.base chain that was causing syntax error in on_drag_hover - Ensure all drag-drop closures have proper type annotations Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The on_drag closure must borrow the drag value (&Rc<Company>) to match ListItem::on_drag's Fn(&T, ...) bound, fixing the E0631 type mismatch that broke compilation of the story crate. Also wire the "Draggable" checkbox to call toggle_draggable (matching the selectable/searchable toggle pattern) so the method is no longer dead code, and rename the unused window parameter to _window. Co-Authored-By: Claude <noreply@anthropic.com>
Member
|
Thanks for the PR. Your approach works, but it's not a complete API design. I tried implementing GPUI's Closing this for now, we can discuss more if you have any questions. Thanks again. |
madcodelife
added a commit
that referenced
this pull request
Aug 3, 2026
…nd drop (#2639) ## Description Implement `InteractiveElement` and `StatefulInteractiveElement` for `ListItem` by delegating to the inner `Stateful<Div>`, the same pattern used by `Button`, `Checkbox`, `Radio`, and `Tab`. - All GPUI native interaction APIs (`on_drag`, `on_drop`, `drag_over`, `can_drop`, `on_hover`, `tooltip`, ...) become directly available on `ListItem`, so rows can act as drag sources and drop targets inside `Tree` or any custom list. - Inherent `on_click` / `on_mouse_down` / `on_mouse_enter` keep their precedence and disabled/separator gating, so existing consumers are unaffected. - Add a "Draggable" toggle to the List story that demonstrates real reordering on drop. - Document drag-and-drop usage in the List docs (en and zh-CN). This supersedes #2553. Exposing the interactive traits gives the full native API surface with unchanged semantics, instead of forwarding `on_drag` / `on_drop` / `on_drag_hover` one method at a time (`on_drag_hover` there is actually plain `on_hover`, which also fires outside of drags). ## How to Test - `cargo test -p gpui-component --lib list_item` — 3 passed - `cargo clippy -- --deny warnings` - `cargo run -- List`, check "Draggable", then drag a row onto another row: a preview follows the cursor, an indicator line on the target row's top or bottom edge shows the insertion position, and dropping reorders the list. Click selection still works.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Add
on_drag,on_drop, andon_drag_hovermethods toListItemthat delegate to the underlying baseStateful<Div>.These methods enable drag-and-drop reordering when
ListItemis used inside aTreeor any custom list layout. Without them, consumers cannot attach drag/drop handlers because thebasefield is private andListItemdoes not implementDeref<Target=Div>.Use case
In Verve (an API co-development platform built with gpui-component), the project tree needs drag-and-drop reordering for API requests and folders. The
tree()component requires its render callback to returnListItem, so consumers have no way to wrap the item in an outerdivwith drag handlers. These three methods solve this by forwarding to the internal base div:The method signatures mirror GPUI's native
Div::on_drag/on_drop/on_hoverAPIs, so they are immediately familiar.What each method does
on_drag<T, W>(value, constructor)— registers a drag value of typeT. When the user drags the row,constructorbuilds a drag-preview entity of typeW: Render. Delegates toself.base.on_drag().on_drop<T>(listener)— called when a drag value of typeTis dropped onto this row. Delegates toself.base.on_drop().on_drag_hover(listener)— called withtruewhen the cursor enters the row during a drag,falsewhen it leaves. Delegates toself.base.on_hover().Break Changes
Fully additive. No existing API changes. Existing
ListItemconsumers continue to work unchanged.How to Test
The
on_drag/on_drop/on_drag_hovermethods can be tested in any story that usesListIteminside a list. The methods delegate directly to the underlyingStateful<Div>, so they inherit all of GPUI's native drag-and-drop behavior.Checklist
cargo fmt --check.AI Assistance Disclosure
🤖 Parts of this PR were generated with AI assistance and subsequently reviewed by a human to match the project's existing code style and patterns. Specifically:
on_click/on_mouse_down/on_mouse_enterbuilder methods and GPUI's nativeDiv::on_drag/on_drop/on_hoverAPIs.list_item.rs.