Stage 17 round 6 (#3): drag-reorder rack tiles with a visual gap
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s
Dragging a rack tile and dropping it back on the rack reorders it: the dragged tile is lifted out (the drag ghost stands in) and the tiles at/after the pointer's drop slot slide right to open a gap there, so the drop position is visible. On drop the rack and its stable ids are permuted (reorderIndices, unit-tested). Reorder applies only with no pending tiles, so it stays a clean permutation; dropping on a board cell still places as before. Server persistence of the order follows (#4).
This commit is contained in:
+20
-3
@@ -9,6 +9,8 @@
|
||||
variant,
|
||||
selected,
|
||||
shuffling = false,
|
||||
draggingId = null,
|
||||
dropIndex = null,
|
||||
ondown,
|
||||
}: {
|
||||
// Each slot carries a stable id that travels with its tile through a shuffle, so the
|
||||
@@ -17,12 +19,18 @@
|
||||
variant: Variant;
|
||||
selected: number | null;
|
||||
shuffling?: boolean;
|
||||
// While a rack tile is being dragged to reorder it, draggingId is its id (hidden here —
|
||||
// the drag ghost stands in) and dropIndex is the slot where a gap opens (Stage 17).
|
||||
draggingId?: number | null;
|
||||
dropIndex?: number | null;
|
||||
ondown: (e: PointerEvent, index: number) => void;
|
||||
} = $props();
|
||||
|
||||
// Used slots are hidden (the rack shifts left, freeing room on the right for the
|
||||
// MakeMove control); the slot still exists in the model for per-tile recall.
|
||||
// MakeMove control); the slot still exists in the model for per-tile recall. While
|
||||
// reordering, the dragged tile is lifted out (the ghost shows it).
|
||||
const visible = $derived(slots.filter((s) => !s.used));
|
||||
const shown = $derived(draggingId == null ? visible : visible.filter((s) => s.id !== draggingId));
|
||||
|
||||
// hop flies a tile to its shuffled position along a low parabola (apogee ≈ half a tile
|
||||
// height). The duration scales with the horizontal distance — i.e. the arc length — so
|
||||
@@ -44,11 +52,12 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="rack" data-rack>
|
||||
{#each visible as slot (slot.id)}
|
||||
<div class="rack" class:reordering={draggingId != null} data-rack>
|
||||
{#each shown as slot, i (slot.id)}
|
||||
<button
|
||||
class="tile"
|
||||
class:selected={selected === slot.index}
|
||||
class:shift={dropIndex != null && i >= dropIndex}
|
||||
data-rack-index={slot.index}
|
||||
animate:hop={shuffling}
|
||||
onpointerdown={(e) => ondown(e, slot.index)}
|
||||
@@ -87,6 +96,14 @@
|
||||
outline: 3px solid var(--accent);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
/* While reordering, tiles at/after the drop slot slide right to open a gap there (one
|
||||
tile width plus the rack gap), so the drop position is visible. */
|
||||
.rack.reordering .tile {
|
||||
transition: transform 0.14s ease;
|
||||
}
|
||||
.tile.shift {
|
||||
transform: translateX(calc(100% + 5px));
|
||||
}
|
||||
.letter {
|
||||
position: absolute;
|
||||
top: 8%;
|
||||
|
||||
Reference in New Issue
Block a user