Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v-hero Layout Transition Not Working as Expected When Removing Items in a List #236

Open
thmsfchtnr opened this issue Dec 20, 2024 · 1 comment

Comments

@thmsfchtnr
Copy link

thmsfchtnr commented Dec 20, 2024

Hey I’m trying to use the v-hero directive from hero-motion to create smooth layout transitions when items in a list are removed. However, the items immediately jump to their new positions instead of transitioning smoothly. Is there a way to make it work?

<template>
  <main class="w-screen h-dvh bg-white">
    <ul class="flex flex-col h-full gap-4 w-full">
      <li
        v-hero
        :layoutId="item.id"
        @click="removeItem(item)"
        v-for="item in items"
        :key="item.id"
        class="bg-blue-500 w-full h-5"
      >
        {{ item.id }}
      </li>
    </ul>
  </main>
</template>

<script lang="ts" setup>
import { directive } from 'hero-motion'
import { ref } from 'vue'
const vHero = directive()

const items = ref([
  {
    id: 1,
    name: 'Item 1',
    description: 'Description for Item 1',
  },
  {
    id: 2,
    name: 'Item 2',
    description: 'Description for Item 2',
  },
  {
    id: 3,
    name: 'Item 3',
    description: 'Description for Item 3',
  },
])

const removeItem = (item) => {
  items.value = items.value.filter((i) => i.id !== item.id)
}
</script>
@tmg0
Copy link
Owner

tmg0 commented Dec 22, 2024

I have created a demo of this on stackblitz -> here

The transition animation doesn't work because hero-motion only captures the current element information when the element is created or deleted, but deleting an element from a list does not trigger this behavior for other elements.

Currently, I'm updating the entire DOM manually using a variable in this demo, but this is not a scalable solution.

And here is the main logic:

<script lang="ts" setup>
import { directive, HeroProvider } from 'hero-motion'
import { ref, nextTick } from 'vue'

const visible = ref(true)
const vHero = directive()

const items = ref([
  {
    id: 1,
    name: 'Item 1',
    description: 'Description for Item 1',
  },
  {
    id: 2,
    name: 'Item 2',
    description: 'Description for Item 2',
  },
  {
    id: 3,
    name: 'Item 3',
    description: 'Description for Item 3',
  },
])

const removeItem = async (item) => {
  visible.value = false
  items.value = items.value.filter((i) => i.id !== item.id)
  await nextTick()
  visible.value = true
}
</script>

<template>
  <HeroProvider as="main" class="w-screen h-dvh bg-white">
    <ul v-if="visible" class="flex flex-col h-full gap-4 w-full">
      <li
        v-hero
        :layoutId="item.id"
        @click="removeItem(item)"
        v-for="item in items"
        :key="item.id"
        class="bg-blue-500 w-full h-5"
      >
        {{ item.id }}
      </li>
    </ul>
  </HeroProvider>
</template>

Maybe expose a method for manual position updates or introduce a global attribute to manage interactions with other elements is a good way. I need to think this further.

Anyway thanks for exposing this issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants