@@ -112,6 +112,10 @@ watch(
112112 { immediate: true },
113113)
114114
115+ // Suppress per-card enter animation when the entire result set is replaced (new search).
116+ // Cards loaded incrementally via scroll should still animate in with the stagger effect.
117+ const suppressAnimation = shallowRef (false )
118+
115119// Reset scroll state when results change significantly (new search)
116120watch (
117121 () => props .results ,
@@ -123,6 +127,10 @@ watch(
123127 (oldResults .length > 0 && newResults [0 ]?.package .name !== oldResults [0 ]?.package .name )
124128 ) {
125129 hasScrolledToInitial .value = false
130+ suppressAnimation .value = true
131+ nextTick (() => {
132+ suppressAnimation .value = false
133+ })
126134 }
127135 },
128136)
@@ -172,9 +180,13 @@ defineExpose({
172180 :show-publisher =" showPublisher"
173181 :index =" index"
174182 :search-query =" searchQuery"
175- class =" motion-safe:animate-fade-in motion-safe:animate-fill-both"
183+ :class ="
184+ !suppressAnimation && 'motion-safe:animate-fade-in motion-safe:animate-fill-both'
185+ "
186+ :style ="
187+ !suppressAnimation ? { animationDelay: `${Math.min(index * 0.02, 0.3)}s` } : {}
188+ "
176189 :filters =" filters"
177- :style =" { animationDelay: `${Math.min(index * 0.02, 0.3)}s` }"
178190 @click-keyword =" emit('clickKeyword', $event)"
179191 />
180192 </div >
@@ -224,8 +236,10 @@ defineExpose({
224236 :show-publisher =" showPublisher"
225237 :index =" index"
226238 :search-query =" searchQuery"
227- class =" motion-safe:animate-fade-in motion-safe:animate-fill-both"
228- :style =" { animationDelay: `${Math.min(index * 0.02, 0.3)}s` }"
239+ :class ="
240+ !suppressAnimation && 'motion-safe:animate-fade-in motion-safe:animate-fill-both'
241+ "
242+ :style =" !suppressAnimation ? { animationDelay: `${Math.min(index * 0.02, 0.3)}s` } : {}"
229243 :filters =" filters"
230244 @click-keyword =" emit('clickKeyword', $event)"
231245 />
0 commit comments