Reorder grid
A drag-to-reorder grid using Motion for Vue's Reorder component, with spring layout animations and drag scaling.
Source code
<script setup lang="ts">
import { Reorder } from 'motion-v'
import { ref } from 'vue'
/**
* ============== Props ================
*/
interface Props {
dragScale?: number
stiffness?: number
damping?: number
}
const props = withDefaults(defineProps<Props>(), {
dragScale: 1.08,
stiffness: 350,
damping: 30,
})
/**
* ============== Data ================
*/
const initialItems = Array.from({ length: 16 }, (_, index) => index + 1)
const items = ref(initialItems)
</script>
<template>
<main class="reorder-stage">
<Reorder.Group
as="div"
v-model:values="items"
class="reorder-grid"
aria-label="Reorderable grid"
>
<Reorder.Item
v-for="item in items"
:key="item"
as="div"
:value="item"
class="reorder-item"
:transition="{
type: 'spring',
stiffness: stiffness,
damping: damping,
}"
:whileDrag="{ scale: dragScale }"
:style="{
backgroundColor: `var(--hue-${(item % 6) + 1})`,
}"
>
{{ String(item).padStart(2, "0") }}
</Reorder.Item>
</Reorder.Group>
</main>
</template>
<style>
.reorder-stage {
display: flex;
align-items: center;
justify-content: center;
touch-action: none;
}
.reorder-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px;
width: min(76vw, 420px);
}
.reorder-item {
display: grid;
place-items: center;
aspect-ratio: 1;
color: var(--background);
cursor: grab;
font-family: var(--font-mono);
font-size: clamp(11px, 2.2vw, 15px);
font-variation-settings: "wght" 600;
user-select: none;
}
.reorder-item:active {
cursor: grabbing;
}
</style>







