Skip to content

Commit

Permalink
fix: add loop animation
Browse files Browse the repository at this point in the history
  • Loading branch information
kalix127 committed Jan 13, 2025
1 parent b6ece8b commit 827a2bc
Showing 1 changed file with 37 additions and 36 deletions.
73 changes: 37 additions & 36 deletions components/content/inspira/ui/animated-list/AnimatedList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,21 @@
>
<!-- Only render the items up to the current index -->
<div
v-for="(item, idx) in itemsToShow"
:key="idx"
v-for="(data, idx) in itemsToShow"
:key="data.id"
v-motion
:initial="getInitial(idx)"
:enter="getEnter(idx)"
:leave="getLeave()"
:class="cn('mx-auto w-full')"
>
<component :is="item" />
<component :is="data.node" />
</div>
</transition-group>
</div>
</template>

<script lang="ts" setup>
import type { Slot, VNodeNormalizedChildren } from "vue";
import { cn } from "~/lib/utils";
interface Props {
Expand All @@ -36,54 +35,56 @@ const props = withDefaults(defineProps<Props>(), {
});
const slots = useSlots();
const index = ref(0);
const displayedItems = ref<{ node: unknown; id: string }[]>([]);
const nextIndex = ref(0);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const slotsArray = ref<any>([]);
onMounted(startLoop);
onMounted(loadComponents);
async function startLoop() {
const notifications = slots.default ? (slots.default()[0].children ?? []) : [];
if (!notifications.length) return;
const itemsToShow = computed(() => {
return slotsArray.value.slice(0, index.value);
});
async function loadComponents() {
slotsArray.value = slots.default ? slots.default()[0].children : [];
while (displayedItems.value.length < notifications.length) {
displayedItems.value.push({
node: notifications[nextIndex.value],
id: `${nextIndex.value}-${Date.now()}`,
});
nextIndex.value = (nextIndex.value + 1) % notifications.length;
await wait(props.delay);
}
while (index.value < slotsArray.value.length) {
index.value++;
while (true) {
displayedItems.value.shift();
displayedItems.value.push({
node: notifications[nextIndex.value],
id: `${nextIndex.value}-${Date.now()}`,
});
nextIndex.value = (nextIndex.value + 1) % notifications.length;
await wait(props.delay);
}
}
const itemsToShow = computed(() => displayedItems.value);
async function wait(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Get initial animation (all items appear with no scale and opacity 0)
function getInitial(idx: number) {
return idx === index.value - 1
? {
scale: 0,
opacity: 0,
}
: undefined; // Only animate the newly added item
return { scale: 0, opacity: 0 };
}
// Get enter animation (only the latest item animates in)
function getEnter(idx: number) {
return idx === index.value - 1
? {
scale: 1,
opacity: 1,
y: 0,
transition: {
type: "spring",
stiffness: 250,
damping: 40,
},
}
: undefined; // Only animate the newly added item
return {
scale: 1,
opacity: 1,
y: 0,
transition: {
type: "spring",
stiffness: 250,
damping: 40,
},
};
}
// Get leave animation (same for all)
Expand Down

0 comments on commit 827a2bc

Please sign in to comment.