Skip to content

Commit e97e29d

Browse files
committed
fix feed ticker animation and highlight margin/padding
1 parent 904a138 commit e97e29d

File tree

2 files changed

+37
-31
lines changed

2 files changed

+37
-31
lines changed

src/components/FeedTicker.tsx

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { formatDistanceToNow } from 'date-fns'
66
import { findLibrary } from '~/libraries'
77

88
const DISPLAY_DURATION = 7000 // 7 seconds in milliseconds
9+
const TRANSITION_DURATION = 500 // 0.5 seconds for crossfade
910

1011
export function FeedTicker() {
1112
// Fetch feed entries with default filters (major, minor releases, include prerelease)
@@ -24,7 +25,8 @@ export function FeedTicker() {
2425
})
2526

2627
const [currentIndex, setCurrentIndex] = React.useState(0)
27-
const [animationKey, setAnimationKey] = React.useState(0)
28+
const [previousIndex, setPreviousIndex] = React.useState<number | null>(null)
29+
const [isTransitioning, setIsTransitioning] = React.useState(false)
2830

2931
const entries = feedQuery.data?.page || []
3032

@@ -33,8 +35,15 @@ export function FeedTicker() {
3335

3436
// Rotate to next item after DISPLAY_DURATION
3537
const rotateTimeout = setTimeout(() => {
38+
setPreviousIndex(currentIndex)
39+
setIsTransitioning(true)
3640
setCurrentIndex((prev) => (prev + 1) % entries.length)
37-
setAnimationKey((prev) => prev + 1)
41+
42+
// Clear previous after transition completes
43+
setTimeout(() => {
44+
setPreviousIndex(null)
45+
setIsTransitioning(false)
46+
}, TRANSITION_DURATION)
3847
}, DISPLAY_DURATION)
3948

4049
return () => clearTimeout(rotateTimeout)
@@ -44,7 +53,8 @@ export function FeedTicker() {
4453
React.useEffect(() => {
4554
if (entries.length > 0) {
4655
setCurrentIndex(0)
47-
setAnimationKey(0)
56+
setPreviousIndex(null)
57+
setIsTransitioning(false)
4858
}
4959
}, [entries.length])
5060

@@ -54,6 +64,7 @@ export function FeedTicker() {
5464
}
5565

5666
const currentEntry = entries[currentIndex]
67+
const previousEntry = previousIndex !== null ? entries[previousIndex] : null
5768
if (!currentEntry) return null
5869

5970
const renderEntry = (entry: typeof currentEntry) => {
@@ -161,43 +172,38 @@ export function FeedTicker() {
161172
width: '100%',
162173
}}
163174
>
164-
{/* Progress bar - full height behind content */}
165-
<div className="absolute inset-0 bg-gray-200/10 dark:bg-gray-700/10 rounded-lg overflow-hidden">
166-
<div
167-
key={animationKey}
168-
className="h-full w-full rounded-lg progress-gradient"
169-
style={{
170-
transformOrigin: 'left',
171-
animation: `progress ${DISPLAY_DURATION}ms linear forwards`,
172-
}}
173-
/>
174-
</div>
175-
176-
<div className="relative z-10 h-full flex items-center">
175+
<div className="h-full flex items-center">
176+
{/* Previous entry fading out */}
177+
{previousEntry && isTransitioning && (
178+
<div
179+
key={`prev-${previousIndex}`}
180+
className="absolute inset-0 flex items-center animate-fade-out"
181+
>
182+
{renderEntry(previousEntry)}
183+
</div>
184+
)}
185+
{/* Current entry fading in */}
177186
<div
178-
key={animationKey}
179-
className="absolute inset-0 flex items-center animate-fade-in"
187+
key={`curr-${currentIndex}`}
188+
className={`absolute inset-0 flex items-center ${isTransitioning ? 'animate-fade-in' : ''}`}
180189
>
181190
{renderEntry(currentEntry)}
182191
</div>
183192
</div>
184193
<style>{`
185-
.progress-gradient {
186-
background: linear-gradient(to right, transparent, rgb(209 213 219 / 0.3));
187-
}
188-
.dark .progress-gradient {
189-
background: linear-gradient(to right, transparent, rgb(75 85 99 / 0.3));
190-
}
191-
@keyframes progress {
192-
from { transform: scaleX(0); }
193-
to { transform: scaleX(1); }
194-
}
195194
@keyframes fadeIn {
196195
from { opacity: 0; }
197196
to { opacity: 1; }
198197
}
198+
@keyframes fadeOut {
199+
from { opacity: 1; }
200+
to { opacity: 0; }
201+
}
199202
.animate-fade-in {
200-
animation: fadeIn 300ms ease-out forwards;
203+
animation: fadeIn 500ms ease-out forwards;
204+
}
205+
.animate-fade-out {
206+
animation: fadeOut 500ms ease-out forwards;
201207
}
202208
`}</style>
203209
</div>

src/components/SearchModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ const Hit = ({
339339
)}
340340
{hierarchyLevels.map((lvl, i, arr) => (
341341
<React.Fragment key={lvl}>
342-
<span className="text-gray-600 dark:text-gray-400 [&_mark]:font-black [&_mark]:!bg-transparent [&_mark]:text-black [&_mark]:dark:text-white">
342+
<span className="text-gray-600 dark:text-gray-400 [&_mark]:font-black [&_mark]:!bg-transparent [&_mark]:text-black [&_mark]:dark:text-white [&_mark]:inline [&_mark]:!p-0 [&_mark]:!m-0 [&_mark]:!rounded-none">
343343
<DecodedHighlight attribute={`hierarchy.${lvl}`} hit={hit} />
344344
</span>
345345
{i < arr.length - 1 && (
@@ -351,7 +351,7 @@ const Hit = ({
351351
))}
352352
</h3>
353353
{hit.content ? (
354-
<p className="text-xs text-gray-600 dark:text-gray-400 mt-0.5 ml-8 line-clamp-2 [&_mark]:font-black [&_mark]:!bg-transparent [&_mark]:text-black [&_mark]:dark:text-white">
354+
<p className="text-xs text-gray-600 dark:text-gray-400 mt-0.5 ml-8 line-clamp-2 [&_mark]:font-black [&_mark]:!bg-transparent [&_mark]:text-black [&_mark]:dark:text-white [&_mark]:inline [&_mark]:!p-0 [&_mark]:!m-0 [&_mark]:!rounded-none">
355355
<Snippet attribute="content" hit={hit} />
356356
</p>
357357
) : null}

0 commit comments

Comments
 (0)