Skip to content

Redesign product associations with animated drag reordering#2578

Merged
glennjacobs merged 4 commits into
2.xfrom
feat/product-association-improvements
Jul 21, 2026
Merged

Redesign product associations with animated drag reordering#2578
glennjacobs merged 4 commits into
2.xfrom
feat/product-association-improvements

Conversation

@glennjacobs

Copy link
Copy Markdown
Contributor

Summary

Reworks the product-associations section on the product edit page into the panel's accordion design, adds ordering support, and gives every manual drag-sort in the panel a smooth, non-oscillating reorder animation.

Product associations

  • Collapsed accordion: each relationship type is a card showing its label, hint, linked-product count and a Link action, expanding to reveal the linked products.
  • Adds a sort column to product_associations (folded into the alpha baseline) and orders the associations() relationship by it, so linking order drives both the panel and the storefront.
  • New links get an incrementing per-type sort; a reorder endpoint (scoped to the owning product and type) persists drag reordering.
  • Each linked product shows its cheapest default-currency price ("From ...") alongside the variant count.
  • Success flash on reorder, mirroring the add action.

Animated drag reordering

  • useDragSort (vertical lists) and useGridSort (2-D grids) implement the dnd-kit slot-transform technique: item order is frozen mid-drag, the target is derived purely from the pointer against captured geometry, displaced items animate via transforms, and the reorder commits once on drop. Because the slot computation never reads live positions, the animation cannot feed back into it.
  • Applied to product associations, collection products, attribute list fields (plain + keyed), and the media tile grid.
  • Media grid caveat: a tile crossing the 2×2 hero slot slides at its own size and settles to the new size on drop (translate cannot resize).

Migration note

The sort column was folded into the baseline create_product_associations_table migration (v2 alpha convention). Existing databases need the column added — migrate:fresh, or an ALTER TABLE for data you want to keep.

Translations

assoc_count, assoc_from_price, assoc_variants and flash_associations_reordered added across all 16 locales.

Testing

  • New/updated tests: sort assignment, reorder isolation, price surfacing; drag tests rewritten to drive the container dragover with stubbed geometry.
  • Green: pest --testsuite core, pest --testsuite panel, phpstan, pint, npm run type-check, npm test (211), npm run build.

🤖 Generated with Claude Code

glennjacobs and others added 4 commits July 21, 2026 22:22
Rework the product-associations section on the product edit page into a
collapsed accordion matching the panel design: each relationship type is a
card showing its label, hint, linked-product count and a Link action, and
expands to reveal the linked products.

- Add a sort column to product_associations (folded into the alpha baseline)
  and order the associations() relationship by it, so linking order drives
  both the panel and storefront display.
- Assign an incrementing per-type sort when associating, and add a reorder
  endpoint scoped to the owning product and type.
- Surface the cheapest default-currency price per linked product for the
  "From ..." label alongside the variant count.
- Add a success flash on reorder, mirroring the add action.
- Add assoc_count / assoc_from_price / assoc_variants / flash_associations_reordered
  across all 16 locales.
- Cover sort assignment, reorder isolation and price surfacing with tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reorder the associations list with slot transforms (the dnd-kit technique)
instead of hover-driven array swaps. Row geometry is captured at dragstart,
the target slot is derived purely from the pointer against that geometry, and
displaced rows animate via translateY; the reorder commits once on drop. The
slot computation never reads live positions, so the animation cannot feed back
into it - eliminating the oscillation a hover-swap + FLIP approach caused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the slot-transform drag-reorder logic out of the associations page into a
useDragSort composable (measures row geometry lazily on the first dragover, so
it works whether the row or just its handle is draggable) and reuse it for the
collection products list and the attribute list fields. A sortableCount bound
lets the plain list keep its trailing add-row un-targetable. Update the
attribute drag tests to drive the container dragover with stubbed row geometry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add useGridSort - the 2-D analogue of useDragSort - and use it for the media
tile grid. Each cell's rect is captured on the first dragover, the target is
the cell nearest the pointer, and displaced cells translate to the slot they
will occupy; the reorder commits once on drop. A cell crossing the hero slot
slides at its own size and settles to the new size on drop (translate cannot
resize). Update the media reorder test to drive the grid dragover with stubbed
cell geometry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-project-automation github-project-automation Bot moved this to Todo in Roadmap Jul 21, 2026
@glennjacobs
glennjacobs merged commit 6fa8dec into 2.x Jul 21, 2026
23 checks passed
@glennjacobs
glennjacobs deleted the feat/product-association-improvements branch July 21, 2026 21:57
@github-project-automation github-project-automation Bot moved this from Todo to Done in Roadmap Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant